Files
Edu/services/parent-bff/docs/nextstep-v2.md

421 lines
29 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.
# parent-bff 模块上下游依赖与工作清单Next Steps v2
> 版本v2
> 日期2026-07-14
> 负责人ai04
> 关联:
>
> - [parent-portal nextstep-v2.md](../../../apps/parent-portal/docs/nextstep-v2.md)
> - [api-gateway nextstep.md](../../api-gateway/docs/nextstep.md)
> - [parent-bff.graphql SDL](../../../packages/shared-ts/contracts/graphql/parent-bff.graphql)
---
## 1. 概述
parent-bff 是家长端聚合层 BFFBackend For Frontend端口 3010基于 NestJS + GraphQL Yoga。负责聚合 iam / core-edu / data-ana / msg 四个下游微服务的 gRPC 接口,为 parent-portal 前端提供场景化 GraphQL API。
**路由路径ARB-022 §24.4 ISSUE-003 方案 A 双 /v1 前缀):**
```
parent-portal
→ POST /api/v1/parent/v1/graphql (前端调用路径)
→ api-gateway registerBffProxy("parent") (剥离 /api/v1/parent)
→ parent-bff:3010 /v1/graphql (BFF 接收路径)
→ GraphqlController @Controller("v1/graphql")
```
**本地 Docker 测试结果2026-07-14DEV_MODE=false不使用 mock**
- ✅ TypeScript 编译零错误(`tsc --noEmit -p tsconfig.test.json`
- ✅ ESLint 零错误(`eslint src test`
- ✅ 单元测试 + 集成测试全通过128 tests, 13 test files
- ✅ Docker 镜像构建成功(`edu/parent-bff:test`
- ✅ 容器启动正常(端口 3010DEV_MODE=false 生产模式)
-`/healthz` 返回 200liveness 通过)
-`/readyz` 返回 200status=degraded下游 gRPC 不可达但 Redis up
-`/v1/graphql` GraphQL 查询正常响应(`{ __typename }``{ data: { __typename: "Query" } }`
-`/v1/graphql` 扩展查询正常(`{ myChildren { id } }``{ data: { myChildren: [] } }`
-`/v1/graphql` Mutation 正常(`mutation { markAllAsRead { count } }``{ data: { markAllAsRead: { count: 0 } } }`
-`/metrics` 返回 Prometheus 指标graphql_requests_total + graphql_duration_seconds
- ✅ 优雅降级:下游 gRPC 不可达时 resolver 返回空数据而非崩溃
---
## 2. 已完成工作v2 全部完成)
### 2.1 P0 阻塞项(已解决)
| # | 工作项 | 状态 | 实现详情 |
| --- | ------------------------------------------------------------------ | ---- | ------------------------------------------------------------------------------------------------------- |
| 1 | GraphQL 端点路径修复(`/graphql``/v1/graphql` | ✅ | controller + yoga + module 三处路径改为 `v1/graphql`,对齐 api-gateway `registerBffProxy` 剥离策略 |
| 2 | GraphQL Schema 扩展至 32 Query + 6 Mutation | ✅ | `packages/shared-ts/contracts/graphql/parent-bff.graphql` 已扩展,对齐 parent-portal 全部 operations |
| 3 | TypeScript 类型定义扩展37+ 个新类型) | ✅ | `src/graphql/types.ts` 新增 ChildBrief/ChildSummary/ChildDetail/ChildGrade/AttendanceRecord 等 37+ 类型 |
| 4 | 全部新 Query/Mutation resolver 实现37 个 resolver builder | ✅ | `src/graphql/resolvers/extended-resolvers.ts` 实现 21 个 Query + 6 个 Mutation resolver |
| 5 | Legacy resolver 修复children/child/selectChild/Child.analytics | ✅ | `index.ts` + `select-child.resolver.ts` + `child.resolver.ts` 恢复并接通真实下游 |
| 6 | JSON scalar 支持 | ✅ | `resolvers/index.ts` 新增 JSONScalar用于 NotificationPreferences.preferences 等动态结构) |
| 7 | Response Mapper 更新 | ✅ | `mapParent` 增加 permissions/schoolId新增 `mapChildBrief` |
| 8 | Notification resolver 兼容旧版/新版 schema | ✅ | `notification.resolver.ts` + `notification-preference.resolver.ts` 同时填充两组字段 |
| 9 | Dockerfile 构建修复 | ✅ | 构建上下文改为 repo root复制 shared-proto + shared-ts + tsconfig.base.json |
| 10 | Proto/Schema 路径解析修复 | ✅ | `grpc.factory.ts` + `schema.ts` 改用 `process.cwd()` 解析,兼容开发/生产模式 |
| 11 | pino 导入修复 | ✅ | `logger.ts``import pino from "pino"` 改为 `import { pino } from "pino"`ESM 兼容) |
### 2.2 关键修复详情
**GraphQL 端点路径ARB-022 §24.4 ISSUE-003 方案 A**
| 文件 | 路径配置 |
| --------------------------------- | -------------------------------- |
| `src/entry/graphql.controller.ts` | `@Controller("v1/graphql")` |
| `src/graphql/yoga.ts` | `graphqlEndpoint: "/v1/graphql"` |
| `src/graphql/graphql.module.ts` | `forRoutes("v1/graphql")` |
**Proto/Schema 路径解析process.cwd() 方式):**
| 文件 | 路径解析 |
| ---------------------------------- | ------------------------------------------------------------------------------- |
| `src/graphql/schema.ts` | `process.cwd() + ../../packages/shared-ts/contracts/graphql/parent-bff.graphql` |
| `src/clients/grpc/grpc.factory.ts` | `process.cwd() + ../../packages/shared-proto/proto` |
**Dockerfile 关键修复:**
- 构建上下文改为 repo root访问 packages/shared-proto + packages/shared-ts
- 复制 `tsconfig.base.json``tsconfig.json` extends `../../tsconfig.base.json`
- runtime stage`--ignore-workspace --ignore-scripts`(避免 workspace 解析 + 跳过 native 构建)
- 运行时保留 `packages/shared-proto` + `packages/shared-ts` 目录结构
---
## 3. 上游依赖(调用 parent-bff 的模块)
### 3.1 api-gatewayai01 负责)— P0
| # | 依赖项 | 用途 | 状态 |
| --- | ------------------------------------------ | ---------------------------------------------------------------------------------- | ---- |
| 1 | `/api/v1/parent/*` 反向代理路由 | 前端请求经 api-gateway 代理到 parent-bff:3010 | ✅ |
| 2 | `registerBffProxy("parent", ...)` 路径重写 | 剥离 `/api/v1/parent`,转发剩余路径(`/v1/graphql`)到 parent-bff | ✅ |
| 3 | JWT 鉴权 + x-user-* 头注入 | api-gateway 校验 JWT 后注入 `x-user-id`/`x-user-roles`/`x-data-scope`/`x-trace-id` | ✅ |
| 4 | CORS 白名单 | `CORS_ORIGINS` 环境变量配置 | ✅ |
| 5 | 限流IP 级令牌桶) | 100 rps突发 20 | ✅ |
| 6 | 熔断(下游 5xx 触发) | `CircuitBreaker("downstream")` | ✅ |
**验证要点:**
- api-gateway 入站 `/api/v1/parent/v1/graphql` → 剥离 `/api/v1/parent` → 转发 `/v1/graphql` 到 parent-bff:3010
- parent-bff GraphqlController 注册在 `/v1/graphql`,接收路径匹配
- 经 api-gateway 代理访问 `http://api-gateway:8080/api/v1/parent/v1/graphql` 应返回 200
### 3.2 parent-portalai15 负责)— P0
| # | 依赖项 | 用途 | 状态 |
| --- | -------------------------------------- | --------------------------------------------------- | ---- |
| 1 | `NEXT_PUBLIC_GRAPHQL_ENDPOINT` 配置 | 前端 GraphQL 客户端调用 `/api/v1/parent/v1/graphql` | ✅ |
| 2 | 32 个 Query + 6 个 Mutation operations | 前端定义的 GraphQL 操作,需 parent-bff schema 对齐 | ✅ |
| 3 | Mock 数据禁用 | `NEXT_PUBLIC_API_MOCKING=disabled`,使用真实后端 | ✅ |
**前端调用路径:**
```
parent-portal → POST /api/v1/parent/v1/graphql
→ api-gateway 剥离 /api/v1/parent
→ parent-bff:3010/v1/graphql
```
---
## 4. 下游依赖parent-bff 调用的模块)
### 4.1 iam 服务ai06 负责gRPC :50052— P0
| # | RPC 方法 | 用途 | 状态 | 说明 |
| --- | --------------------------------- | ------------------------------ | ---- | ---------------------------------------------------------- |
| 1 | `getUserInfo(userId)` | 获取家长个人信息 | ✅ | `GrpcIamClient.getUserInfo`,用于 `me`/`currentUser` Query |
| 2 | `getChildrenByParent(parentId)` | 获取家长绑定的孩子列表 | ✅ | `GrpcIamClient.getChildrenByParent`ChildGuard 缓存 30s |
| 3 | `getViewports(userId)` | 获取家长可见视口 | ✅ | `GrpcIamClient.getViewports` |
| 4 | `getEffectivePermissions(userId)` | 获取家长有效权限 | ✅ | `GrpcIamClient.getEffectivePermissions` |
| 5 | `GET /healthz` 端点 | /readyz 下游健康检查 | ⏳ | iam 服务容器未运行,/readyz 报告 down |
| 6 | `GET /.well-known/jwks.json` | RS256 公钥集api-gateway 用) | ⏳ | iam 服务容器未运行 |
**环境变量:** `IAM_GRPC_TARGET=iam:50052`Docker 网络)/ `localhost:50052`(本地开发)
**影响:** iam 不可达时,`me`/`currentUser`/`children`/`myChildren` 等核心 Query 降级返回空数据。
### 4.2 core-edu 服务ai07 负责gRPC :50053— P0
| # | RPC 方法 | 用途 | 状态 | 说明 |
| --- | -------------------------------- | -------------------- | ---- | ------------------------------------------------- |
| 1 | `listGradesByStudent(studentId)` | 孩子成绩列表 | ✅ | 用于 `childGrades`/`childSummary`/`childDetail` |
| 2 | `listHomeworkByClass(classId)` | 班级作业列表 | ✅ | 用于 `childHomework`/`childSummary`/`childDetail` |
| 3 | `listExamsByClass(classId)` | 班级考试列表 | ✅ | 用于 `childExams`/`childSummary`/`childDetail` |
| 4 | `getClass(classId)` | 班级信息 | ⚠️ | ISSUE-008: proto 缺 ClassService当前返回默认值 |
| 5 | `GET /healthz` 端点 | /readyz 下游健康检查 | ⏳ | core-edu 服务容器未运行 |
**环境变量:** `CORE_EDU_GRPC_TARGET=core-edu:50053`Docker 网络)/ `localhost:50053`(本地开发)
**降级查询:** `childAttendance`/`childExamResult`/`childReportCard`/`childLeaveRequests`/`academicYears`/`childClasses`/`createLeaveRequest`/`exportChildGrades` 在 RPC 未就绪时降级返回空数据。
### 4.3 data-ana 服务ai09 负责gRPC :50055— P1
| # | RPC 方法 | 用途 | 状态 | 说明 |
| --- | ---------------------------------------------- | -------------------- | ---- | ------------------------------------- |
| 1 | `getStudentWeakness(studentId, subjectId)` | 学生薄弱知识点 | ✅ | 用于 `childWeakness`/`childAnalytics` |
| 2 | `getLearningTrend(studentId, start, end)` | 学习趋势 | ✅ | 用于 `childTrend`/`childAnalytics` |
| 3 | `getClassPerformance(classId, subjectId, ...)` | 班级绩效 | ✅ | 用于 `classRank`/`classAverage` 计算 |
| 4 | `GET /healthz` 端点 | /readyz 下游健康检查 | ⏳ | data-ana 服务容器未运行 |
**环境变量:** `DATA_ANA_GRPC_TARGET=data-ana:50055`Docker 网络)/ `localhost:50055`(本地开发)
**降级查询:** `childGrowthArchive`/`childLearningPath`/`childErrorBookStats`/`childTopWrongQuestions`/`childWeakKps`/`childMasterySummary`/`childDiagnosticReports`/`childPracticeStats`/`childPracticeSessions` 在 RPC 未就绪时降级返回空数据。
### 4.4 msg 服务ai08 负责gRPC :50056— P1
| # | RPC 方法 | 用途 | 状态 | 说明 |
| --- | -------------------------------------- | -------------------- | ---- | ------------------------------------------ |
| 1 | `listNotifications(parentId, unread)` | 通知列表 | ✅ | 用于 `myNotifications`/`notifications` |
| 2 | `markAsRead(notificationId)` | 标记已读 | ✅ | 用于 `markAsRead`/`markAllAsRead` Mutation |
| 3 | `getNotificationPreferences(parentId)` | 通知偏好 | ⚠️ | proto 未定义 RPCgRPC 实现返回默认值 |
| 4 | `updateNotificationPreferences(...)` | 更新通知偏好 | ⚠️ | proto 未定义 RPCgRPC 实现返回输入 |
| 5 | `GET /healthz` 端点 | /readyz 下游健康检查 | ⏳ | msg 服务容器未运行 |
**环境变量:** `MSG_GRPC_TARGET=msg:50056`Docker 网络)/ `localhost:50056`(本地开发)
### 4.5 Redis基础设施— P0
| # | 依赖项 | 用途 | 状态 |
| --- | ------------------ | --------------------------------------------------- | ---- |
| 1 | `redis://...:6379` | ChildGuard 缓存 + dashboard/grades/permissions 缓存 | ✅ |
**环境变量:** `REDIS_URL=redis://edu-redis:6379`Docker 网络)/ `redis://localhost:6379`(本地开发)
**验证结果:** 容器内 Redis 连接成功(`/readyz` 报告 redis:uplatency_ms=30
### 4.6 降级模式说明
以下 Query 在下游 RPC 未就绪时降级返回空数据(不阻塞前端渲染):
| Query | 降级行为 | 待补全的下游 RPC |
| ------------------------ | ----------------- | ----------------------------- |
| `childAttendance` | 返回空数组 | core-edu AttendanceService |
| `childExamResult` | 返回 null | core-edu ExamResultService |
| `childReportCard` | 返回 null | core-edu ReportCardService |
| `childGrowthArchive` | 返回空 dataPoints | data-ana GrowthArchiveService |
| `childLearningPath` | 返回空数组 | data-ana LearningPathService |
| `childErrorBookStats` | 返回零值 | data-ana ErrorBookService |
| `childTopWrongQuestions` | 返回空数组 | data-ana ErrorBookService |
| `childWeakKps` | 返回空数组 | data-ana WeakKpsService |
| `childMasterySummary` | 返回零值 | data-ana MasteryService |
| `childDiagnosticReports` | 返回空数组 | data-ana DiagnosticService |
| `childPracticeStats` | 返回零值 | data-ana PracticeService |
| `childPracticeSessions` | 返回空数组 | data-ana PracticeService |
| `childCoursePlans` | 返回空数组 | content CoursePlanService |
| `childCoursePlanDetail` | 返回 null | content CoursePlanService |
| `childLessonPlans` | 返回空数组 | content LessonPlanService |
| `childLessonPlanDetail` | 返回 null | content LessonPlanService |
| `childElective` | 返回空数组 | content ElectiveService |
| `childLeaveRequests` | 返回空数组 | core-edu LeaveRequestService |
| `academicYears` | 返回空数组 | core-edu AcademicYearService |
| `childClasses` | 返回空数组 | classes ClassService |
| `createLeaveRequest` | 返回 PENDING 状态 | core-edu LeaveRequestService |
| `exportChildGrades` | 返回临时 URL | core-edu ExportService |
---
## 5. Docker 本地测试
### 5.1 镜像构建
```bash
# 在仓库根目录执行(需要访问 packages/shared-proto + packages/shared-ts + tsconfig.base.json
docker build -t edu/parent-bff:test -f services/parent-bff/Dockerfile .
```
### 5.2 容器启动
```bash
# 加入 edu-full_default 网络(与 Redis/MySQL/Kafka 等基础设施同网络)
docker run -d \
--name edu-parent-bff-test \
--network edu-full_default \
-p 3010:3010 \
-e NODE_ENV=production \
-e DEV_MODE=false \
-e PORT=3010 \
-e REDIS_URL=redis://edu-redis:6379 \
-e IAM_GRPC_TARGET=iam:50052 \
-e CORE_EDU_GRPC_TARGET=core-edu:50053 \
-e DATA_ANA_GRPC_TARGET=data-ana:50055 \
-e MSG_GRPC_TARGET=msg:50056 \
-e CORS_ORIGINS=http://localhost:4002 \
-e GRAPHQL_INTROSPECTION_ENABLED=true \
edu/parent-bff:test
```
### 5.3 健康检查验证
```bash
# liveness返回 200
curl http://localhost:3010/healthz
# {"status":"ok","service":"parent-bff","timestamp":"..."}
# readiness返回 200status=degraded 因为下游 gRPC 不可达)
curl http://localhost:3010/readyz
# {"status":"degraded","checks":{"iam":{"status":"down",...},"redis":{"status":"up",...}}}
# Prometheus 指标
curl http://localhost:3010/metrics
```
### 5.4 GraphQL 端点验证
```bash
# 必须携带 x-user-* 头api-gateway 注入)
curl -X POST http://localhost:3010/v1/graphql \
-H "Content-Type: application/json" \
-H "x-user-id: parent-001" \
-H "x-user-roles: parent" \
-H "x-data-scope: CHILDREN:child-001" \
-H "x-trace-id: test-trace-001" \
-d '{"query":"{ __typename }"}'
# {"data":{"__typename":"Query"}}
# 扩展查询(优雅降级)
curl -X POST http://localhost:3010/v1/graphql \
-H "Content-Type: application/json" \
-H "x-user-id: parent-001" \
-H "x-user-roles: parent" \
-d '{"query":"{ myChildren { id name } }"}'
# {"data":{"myChildren":[]}}
# Mutation
curl -X POST http://localhost:3010/v1/graphql \
-H "Content-Type: application/json" \
-H "x-user-id: parent-001" \
-H "x-user-roles: parent" \
-d '{"query":"mutation { markAllAsRead { count } }"}'
# {"data":{"markAllAsRead":{"count":0}}}
```
---
## 6. 后续其他模块配合工作
### 6.1 待下游服务补全的 RPCP1
| 服务 | 待补全 RPC | 用途 | 影响 Query/Mutation |
| -------- | ---------------------------------- | --------------------- | ------------------------------------------------------------- |
| core-edu | `AttendanceService.ListAttendance` | 孩子考勤记录 | `childAttendance` |
| core-edu | `ExamResultService.GetExamResult` | 考试成绩详情 | `childExamResult` |
| core-edu | `ReportCardService.GetReportCard` | 成绩单 | `childReportCard` |
| core-edu | `LeaveRequestService.List/Create` | 请假记录 | `childLeaveRequests`/`createLeaveRequest` |
| core-edu | `AcademicYearService.List` | 学年列表 | `academicYears` |
| core-edu | `ClassService.GetClass` | 班级信息ISSUE-008 | `childClasses` |
| core-edu | `ExportService.ExportGrades` | 成绩导出 | `exportChildGrades` |
| data-ana | `GrowthArchiveService.Get` | 成长档案 | `childGrowthArchive` |
| data-ana | `LearningPathService.List` | 学习路径 | `childLearningPath` |
| data-ana | `ErrorBookService.GetStats/List` | 错题本统计/列表 | `childErrorBookStats`/`childTopWrongQuestions` |
| data-ana | `WeakKpsService.List` | 薄弱知识点 | `childWeakKps` |
| data-ana | `MasteryService.GetSummary` | 掌握度汇总 | `childMasterySummary` |
| data-ana | `DiagnosticService.List` | 诊断报告 | `childDiagnosticReports` |
| data-ana | `PracticeService.GetStats/List` | 练习统计/会话 | `childPracticeStats`/`childPracticeSessions` |
| content | `CoursePlanService.List/Get` | 课程计划 | `childCoursePlans`/`childCoursePlanDetail` |
| content | `LessonPlanService.List/Get` | 备课计划 | `childLessonPlans`/`childLessonPlanDetail` |
| content | `ElectiveService.List` | 选修课 | `childElective` |
| msg | `NotificationPreferencesService` | 通知偏好查询/更新 | `myNotificationPreferences`/`updateMyNotificationPreferences` |
### 6.2 端到端联调待办P1
| # | 联调项 | 触发条件 |
| --- | ----------------------------------------------- | ---------------------------------------------------------- |
| 1 | iam 服务容器启动 + JWKS 端点就绪 | iam 服务 Docker 化 |
| 2 | core-edu 服务容器启动 + gRPC 端口就绪 | core-edu 服务 Docker 化 |
| 3 | data-ana 服务容器启动 + gRPC 端口就绪 | data-ana 服务 Docker 化 |
| 4 | msg 服务容器启动 + gRPC 端口就绪 | msg 服务 Docker 化 |
| 5 | parent-bff 加入 deploy compose | `infra/docker-compose.deploy.yml` 补充 parent-bff 服务定义 |
| 6 | parent-portal → api-gateway → parent-bff 端到端 | 所有服务容器就绪后执行 |
### 6.3 给下游模块的工作要求
**给 iamai06**
- 补全 `getChildrenByParent` RPC返回 ChildDto 列表,含 id/name/grade/classId/className/gradeId
- 补全 `getViewports` RPC返回 ViewportDto 列表)
- 补全 `getEffectivePermissions` RPC返回 permissions 数组)
- 启动 `/healthz` 端点供 parent-bff /readyz 探测
**给 core-eduai07**
- 补全 `ClassService.GetClass` RPCISSUE-008 仲裁)
- 补全 `AttendanceService`/`ExamResultService`/`ReportCardService`/`LeaveRequestService`/`AcademicYearService`/`ExportService`
- 启动 `/healthz` 端点供 parent-bff /readyz 探测
**给 data-anaai09**
- 补全 `GrowthArchiveService`/`LearningPathService`/`ErrorBookService`/`WeakKpsService`/`MasteryService`/`DiagnosticService`/`PracticeService`
- 启动 `/healthz` 端点供 parent-bff /readyz 探测
**给 msgai08**
- 补全 `NotificationPreferencesService`Get/Update
- 启动 `/healthz` 端点供 parent-bff /readyz 探测
**给 api-gatewayai01**
- 确认 `/api/v1/parent/*` 路由已注册(已完成)
- 确认 `registerBffProxy("parent", ...)` 路径重写剥离 `/api/v1/parent`(已完成)
**给 parent-portalai15**
- 确认 `NEXT_PUBLIC_GRAPHQL_ENDPOINT=/api/v1/parent/v1/graphql`(已完成)
- 确认 32 Query + 6 Mutation operations 与 parent-bff.graphql schema 对齐(已完成)
---
## 7. 关键文件路径
| 文件 | 用途 |
| -------------------------------------------------------------------- | ------------------------------------------------- |
| `packages/shared-ts/contracts/graphql/parent-bff.graphql` | GraphQL Schema 契约32Q + 6M前后端共享唯一源 |
| `services/parent-bff/src/entry/graphql.controller.ts` | Controller路由 `v1/graphql` |
| `services/parent-bff/src/graphql/yoga.ts` | Yoga 实例(端点 `/v1/graphql` |
| `services/parent-bff/src/graphql/graphql.module.ts` | Module中间件路由 `v1/graphql` |
| `services/parent-bff/src/graphql/schema.ts` | SDL 加载process.cwd() 解析路径) |
| `services/parent-bff/src/graphql/resolvers/index.ts` | Resolver 注册(含 DateTime + JSON scalar |
| `services/parent-bff/src/graphql/resolvers/extended-resolvers.ts` | 37 个新 resolver builder |
| `services/parent-bff/src/graphql/resolvers/child.resolver.ts` | legacy childAnalytics resolver |
| `services/parent-bff/src/graphql/resolvers/select-child.resolver.ts` | legacy selectChild Mutation resolver |
| `services/parent-bff/src/graphql/types.ts` | TypeScript 类型定义37+ 个新类型) |
| `services/parent-bff/src/aggregation/response-mapper.ts` | DTO → GraphQL Type 映射 |
| `services/parent-bff/src/clients/grpc/grpc.factory.ts` | gRPC 客户端工厂process.cwd() 解析 proto 路径) |
| `services/parent-bff/src/config/env.ts` | Zod 环境变量校验 |
| `services/parent-bff/Dockerfile` | Docker 构建多阶段repo root 上下文) |
---
## 8. 已完成项汇总
| 工作项 | 状态 | 验证方式 |
| -------------------------------------------- | ---- | ------------------------------------------------------------- |
| GraphQL 端点路径修复(`/v1/graphql` | ✅ | Docker 测试 `/v1/graphql` 返回 200 |
| GraphQL Schema 扩展32Q + 6M | ✅ | `{ __typename }` 返回 Query 类型 |
| TypeScript 类型定义扩展37+ 个新类型) | ✅ | `tsc --noEmit` 零错误 |
| 全部 resolver 实现37 个 resolver builder | ✅ | `{ myChildren { id } }` 返回空数组(降级正常) |
| Legacy resolver 修复 | ✅ | selectChild/Child.analytics resolver 恢复 |
| JSON scalar 支持 | ✅ | NotificationPreferences.preferences 字段可用 |
| Response Mapper 更新 | ✅ | mapParent 含 permissions/schoolIdmapChildBrief 新增 |
| Notification resolver 兼容旧版/新版 schema | ✅ | 同时填充 type/content 和 eventType/body |
| Dockerfile 构建修复 | ✅ | `edu/parent-bff:test` 构建成功 |
| Proto/Schema 路径解析修复 | ✅ | 容器启动日志显示 gRPC client 创建成功 |
| pino 导入修复 | ✅ | 容器启动无错误 |
| TypeScript 编译零错误 | ✅ | `tsc --noEmit -p tsconfig.test.json` 通过 |
| ESLint 零错误 | ✅ | `eslint src test` 通过 |
| 单元测试 + 集成测试通过 | ✅ | 128 tests, 13 test files 全部通过 |
| Docker 镜像构建 | ✅ | `edu/parent-bff:test` 构建成功 |
| Docker 容器运行验证 | ✅ | /healthz 200 + /readyz 200 + /v1/graphql 200 + /metrics 200 |
| 优雅降级验证 | ✅ | 下游 gRPC 不可达时返回空数据而非崩溃 |
| 可观测性验证 | ✅ | /metrics 含 graphql_requests_total + graphql_duration_seconds |
| Mutation 验证 | ✅ | `markAllAsRead { count }` 返回 0 |
---
**本文件由 ai04 维护。parent-bff 已完成 v2 全部工作并通过本地 Docker 测试DEV_MODE=false连接真实 Redis下游 gRPC 不可达时优雅降级。等待下游应用服务iam/core-edu/data-ana/msg容器就绪后即可端到端联调。**