# parent-portal 问题记录

> 负责人：ai15
> 关联：[coord.md](../coord.md)、[contracts/parent-portal_contract.md](../contracts/parent-portal_contract.md)
> 规则：AI 遇到问题时在此追加条目，coord 仲裁后更新状态

---

## §0 已有仲裁核查（ai15 复核 ARB-001 / ARB-002 落地情况）

> ai15 接管 parent-portal 后，核查 coord 已发布的两项仲裁（ARB-001 teacher-bff GraphQL schema、ARB-002 MF Shell 暴露清单）在 parent-portal 文档中的落地情况。

### 0.1 ARB-001（teacher-bff GraphQL schema 第一版）核查

| 核查项                    | ARB-001 结论      | parent-portal 落地情况                                                   | 状态      |
| ------------------------- | ----------------- | ------------------------------------------------------------------------ | --------- |
| BFF 用 GraphQL（非 REST） | ✅ 已裁决 GraphQL | 01-understanding §3.1 + 02-architecture-design §4.1 全部描述为 REST 消费 | ❌ 未落地 |
| ActionState 信封          | ✅ 已裁决         | 01 §3.2 已对齐                                                           | ✅        |
| 错误码前缀路由            | ✅ 已裁决         | 01 §3.2 + 02 §6.2 已对齐                                                 | ✅        |

**结论**：ARB-001 的核心裁决（BFF = GraphQL）在 parent-portal 的 01/02 文档中**未落地**，01 §3.1 与 02 §4.1 仍按 REST 编写，与 [parent-bff_contract.md](../contracts/parent-bff_contract.md) §1.3（GraphQL 端点 :3010）和 [matrix.md](../matrix.md) §3（parent-bff GraphQL）直接冲突。提请 ISSUE-001。

### 0.2 ARB-002（MF Shell 暴露清单）核查

| 核查项                              | ARB-002 结论 | parent-portal 落地情况                                                                                                                 | 状态      |
| ----------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| Shell 暴露 GraphQLProvider          | ✅ 已裁决    | 01 §4 技术栈未列 urql/GraphQL client；02 §4.1 用 `useApi()`（REST ApiClient）而非 `useGraphQLClient()`                                 | ❌ 未落地 |
| MF shared 含 urql/graphql/@edu/*    | ✅ 已裁决    | 02 §1.2 `shared` 仅列 react/react-dom/@tanstack/react-query/zustand/nuqs，缺 urql/graphql/@edu/ui-tokens/@edu/ui-components/@edu/hooks | ❌ 未落地 |
| Shell 暴露 AppShell                 | ✅ 已裁决    | 01 §9.1 + 02 §7.1 已对齐                                                                                                               | ✅        |
| feature flag NEXT_PUBLIC_MF_ENABLED | ✅ 已裁决    | 01/02 均未提及                                                                                                                         | ❌ 未落地 |

**结论**：ARB-002 关于 GraphQL client 与 MF shared 的裁决在 parent-portal 文档中**部分未落地**。提请 ISSUE-002。

---

## 问题列表

<!--
追加条目格式：

### ISSUE-[编号]-[AI标识]：[标题]

- **提请方**：aiXX
- **日期**：YYYY-MM-DD
- **类型**：契约不明确 / 工作量超批 / 前置依赖缺失 / 编号冲突 / 其他
- **描述**：[详细描述问题]
- **建议方案**：[AI 的建议]
- **状态**：待 coord 仲裁 / 已裁决（见 coord.md §X）
-->

### ISSUE-001-ai15：01/02 文档 REST 消费 parent-bff 与 ARB-001 GraphQL 裁决冲突

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：契约不明确（文档与已裁决架构冲突）
- **描述**：
  - 01-understanding.md §3.1 列出 parent-portal 经 REST 消费 parent-bff：`GET /parent/viewports`、`GET /parent/children`、`POST /parent/children/:childId/select`、`GET /parent/notifications`、`PUT /parent/notification-preferences` 等
  - 02-architecture-design.md §4.1 `useParentApi` 实现全部基于 `api.get()`/`api.post()` REST 调用
  - 但 ARB-001（coord.md §1）已裁决 BFF 用 GraphQL；[parent-bff_contract.md](../contracts/parent-bff_contract.md) §1.3 明确 parent-bff 提供 `POST /graphql`（:3010）；[matrix.md](../matrix.md) §3 确认 parent-bff = GraphQL
  - parent-portal 自己的 [contract.md](../contracts/parent-portal_contract.md) §2.3-2.4 也写明消费 GraphQL（`POST /api/parent/graphql`，Query 域：currentUser/myChildren/childSummary/childGrades 等）
  - **文档内部自相矛盾**：01/02 用 REST，contract.md 用 GraphQL
- **建议方案**：
  1. coord 确认 parent-portal 消费 parent-bff **统一用 GraphQL**（与 ARB-001、parent-bff contract、matrix.md 一致）
  2. ai15 据此修订 01 §3.1（改为 GraphQL Query/Mutation 域）、§3.1.1（X-Fields 字段裁剪改为 GraphQL query 字段选择）、02 §4.1（`useParentApi` 改为 GraphQL hooks）、§4.2（TanStack Query 约定配合 GraphQL operations）、§11.3 未决设计决策 #2（移除，已裁决）
  3. 若 coord 另有裁决（如 parent-portal 特殊走 REST），以 coord 裁决为准
- **状态**：待 coord 仲裁

### ISSUE-002-ai15：MF shared 配置缺 urql/graphql/@edu/* 与 ARB-002 冲突

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：契约不明确（文档与已裁决 MF 配置冲突）
- **描述**：
  - 02-architecture-design.md §1.2 MF `shared` 配置仅列：`react`、`react-dom`、`@tanstack/react-query`、`zustand`、`nuqs`
  - ARB-002（coord.md §2）裁决的 `shared` 应包含：`react`、`react-dom`、`urql`、`graphql`、`@edu/ui-tokens`、`@edu/ui-components`、`@edu/hooks`
  - 缺失 `urql`/`graphql` 会导致 Remote 与 Shell 各加载一份 GraphQL client 实例，破坏单例，引发缓存不一致与重复请求
  - 缺失 `@edu/*` 会导致设计令牌/UI 组件/Hooks 各加载一份
  - 同时 01 §4 技术栈表未列 GraphQL client（urql），与 ARB-002 Shell 暴露 GraphQLProvider 矛盾
- **建议方案**：
  1. coord 确认 parent-portal MF `shared` 必须包含 ARB-002 全部 7 项（react/react-dom/urql/graphql/@edu/ui-tokens/@edu/ui-components/@edu/hooks）
  2. ai15 修订 02 §1.2 `shared` 配置 + 01 §4 技术栈表（新增 urql + GraphQL client 行）
  3. 02 §4.1 `useParentApi` 改为从 Shell 暴露的 `useGraphQLClient()` 获取 urql client，不再用 REST ApiClient
- **状态**：待 coord 仲裁

### ISSUE-003-ai15：switch-child 端点在 01/02 文档间不一致

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：契约不明确（文档内部不一致）
- **描述**：
  - 01-understanding.md §3.1 列 `POST /parent/children/:childId/select`
  - 02-architecture-design.md §2.2 + §4.1 用 `POST /api/v1/parent/switch-child`（body 携带 childId）
  - 两处路径与语义均不一致（URL param vs body param）
  - parent-bff contract.md 未列 switch-child（其 §1.3 仅列 Query/Mutation 域，未细到 switch-child）
- **建议方案**：
  1. 若走 GraphQL（依 ISSUE-001 裁决）：switch-child 应为 `mutation switchChild(childId: ID!): SwitchChildPayload!`，不存在 REST 路径
  2. 若走 REST：统一为 `POST /api/v1/parent/switch-child`（body 携带 childId，与 02 一致），修订 01 §3.1
  3. 请 coord 一并明确 parent-bff GraphQL schema 是否包含 `switchChild` Mutation（当前 parent-bff contract.md 未列）
- **状态**：待 coord 仲裁

### ISSUE-004-ai15：登录端点在 01 / contract.md / matrix.md 间三方不一致

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：契约不明确（跨文档不一致）
- **描述**：
  - 01-understanding.md §3.1 列 `POST /iam/login`
  - parent-portal_contract.md §2.3 列 `POST /api/auth/login`
  - matrix.md §5 规范 iam 经 api-gateway 代理路径为 `/api/v1/iam/*`
  - 三处不一致，且 contract.md 的 `/api/auth/login` 路径在 matrix.md 中不存在
- **建议方案**：
  1. 统一为 `POST /api/v1/iam/login`（与 matrix.md §5 + 01 §3.1 的 `/api/v1/iam/*` 前缀一致）
  2. ai15 修订 contract.md §2.3 路径
  3. 注意：登录是 parent-portal 唯一可能走 REST（非 GraphQL）的端点，因登录前无 JWT，GraphQL endpoint 需鉴权。请 coord 确认登录是否走 REST `/api/v1/iam/login`，其余走 GraphQL
- **状态**：待 coord 仲裁

### ISSUE-005-ai15：02 §11.3 未决设计决策 #2 "GraphQL vs REST" 已由 ARB-001 裁决，应移除

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：其他（文档过时）
- **描述**：
  - 02-architecture-design.md §11.3 第 2 项将 "GraphQL vs REST" 列为未决设计决策，建议 "P4 用 REST，后续若 BFF 切 GraphQL 再引入 urql"
  - 但 ARB-001（coord.md §1）已于 2026-07-09 裁决 BFF 用 GraphQL，且 parent-bff contract.md 确认 GraphQL
  - 此项已过时，会误导后续开发
- **建议方案**：
  1. coord 确认 ARB-001 适用于 parent-portal（即 parent-portal P4 起必须用 GraphQL 消费 parent-bff）
  2. ai15 移除 02 §11.3 第 2 项，改为 "已裁决：见 ARB-001，parent-portal 用 GraphQL 消费 parent-bff"
- **状态**：待 coord 仲裁

### ISSUE-006-ai15：contract.md §1.2 将前端页面路由误标为 HTTP 端点

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：其他（文档分类错误）
- **描述**：
  - parent-portal_contract.md §1.2 "HTTP 端点" 列出：`GET /`、`GET /children`、`GET /child/:id/summary`、`GET /child/:id/grades` 等
  - 但 parent-portal 是 Next.js 前端应用，这些是**前端页面路由**（SSR/CSR 路由），不是对外 HTTP API 端点
  - 将页面路由放在 "HTTP 端点" 表中会误导下游消费方以为这些是 REST API
  - 且这些路由与 01 §8 L2 路由表（`/parent/dashboard`、`/parent/children` 等）路径还不一致（contract 用 `/children`，01 用 `/parent/children`）
- **建议方案**：
  1. coord 确认 parent-portal 作为前端 Remote，不对外提供 HTTP API 端点（§1.2 应为"无"）
  2. ai15 将 contract.md §1.2 改为 "无（parent-portal 是前端 Remote，不对外提供 HTTP API）"，页面路由信息保留在 01 §8 L2 路由表中，不进 contract.md
  3. 若需保留 MF 暴露信息，归入 §1.6 微前端架构（已有）
- **状态**：待 coord 仲裁

### ISSUE-007-ai15：contract.md §1.6 module-federation.config.ts 与 02 next.config.js 不一致

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：其他（文档内部不一致）
- **描述**：
  - parent-portal_contract.md §1.6 列 MF 配置文件为 `apps/parent-portal/module-federation.config.ts`
  - 02-architecture-design.md §1.2 MF 配置写在 `next.config.js` 中（用 `NextFederationPlugin`）
  - 两处文件名与位置不一致
- **建议方案**：
  1. 统一为 `apps/parent-portal/next.config.js`（与 02 + teacher-portal Shell 一致，Next.js 项目 MF 配置应在 next.config.js）
  2. ai15 修订 contract.md §1.6
- **状态**：待 coord 仲裁

### ISSUE-008-ai15：contract.md §2.3 GraphQL 路径前缀与 matrix.md 不一致

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：契约不明确（跨文档不一致）
- **描述**：
  - parent-portal_contract.md §2.3 列 `POST /api/parent/graphql`
  - matrix.md §5 规范 api-gateway 代理 parent-bff 路径为 `/api/v1/parent/*`
  - 缺 `v1` 版本号
- **建议方案**：
  1. 统一为 `POST /api/v1/parent/graphql`（与 matrix.md §5 一致）
  2. ai15 修订 contract.md §2.3 + §2.4
- **状态**：待 coord 仲裁

### ISSUE-009-ai15：parent-bff GraphQL schema 是否包含 switchChild Mutation 未明确

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：前置依赖缺失（上游契约不全）
- **描述**：
  - parent-bff_contract.md §1.3 列出的 Query/Mutation 域未包含 "switchChild"（切换当前选中子女）
  - 01-understanding.md §2.2 + 02 §2.2 描述 parent-portal 需调用 `POST /parent/switch-child` 切换子女
  - 若走 GraphQL（依 ISSUE-001），parent-bff 需提供 `mutation switchChild(childId: ID!): SwitchChildPayload!`
  - 但 parent-bff contract 未列此 Mutation，且 iam.GetChildrenByParent 已返回子女列表，切换子女是否需后端记录（还是纯前端 localStorage）需明确
- **建议方案**：
  1. 请 coord 协调 ai05（parent-bff）确认：switchChild 是 GraphQL Mutation 还是纯前端状态（localStorage + Zustand）
  2. 若纯前端：01/02 移除 `POST /parent/switch-child` 调用，改为 `useChildSwitcher` 直接写 Zustand + localStorage
  3. 若需后端记录：请 ai05 在 parent-bff contract.md §1.3 补充 `switchChild` Mutation
- **状态**：待 coord 仲裁

### ISSUE-010-ai15：iam GetChildrenByParent 接口缺失（P0 阻塞，跨模块）

- **提请方**：ai15
- **日期**：2026-07-10
- **类型**：前置依赖缺失（跨模块，承自 parent-bff §7.1）
- **描述**：
  - 01-understanding.md §3.1 注明：iam 缺失 "家长-学生关联查询" 接口（`GetChildrenByParent` proto + `GET /iam/children` REST + `iam_student_guardians` 表三缺失）
  - parent-bff_contract.md §2.1 也标注 "核心依赖 I3/ISSUE-047 裁决"
  - parent-bff_contract.md §3.1 标注 "iam gRPC 50052 启用（ai06）—— 核心依赖 GetChildrenByParent（I3/ISSUE-047 裁决）"
  - 此为 parent-portal 多子女场景的 P0 阻塞项，ai06（iam）需在 P3 收尾前补全
  - ai15 在此提请，请 coord 跟踪 ai06 进度并确认补全时间点
- **建议方案**：
  1. coord 确认 ai06 补全 `GetChildrenByParent` 的时间点（应在 P4 启动前）
  2. 在补全前，parent-portal 用 mock（固定 2 个子女）开发，mock 数据与 parent-bff mock 一致（student-001 + student-002）
- **状态**：待 coord 仲裁

---

## §1 已裁决问题

> 详见 [coord.md §22 ARB-020](../coord.md) 完整仲裁章节

### 1.1 仲裁结论汇总（coord 2026-07-10）

| ISSUE | 标题                                            | 仲裁结论摘要                                                                                                | 执行方                         |
| ----- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------ |
| 001   | 01/02 文档 REST 消费 parent-bff 与 ARB-001 冲突 | ✅ 统一 GraphQL 消费（对齐 ARB-018 ISSUE-005 跨模块裁决）                                                   | ai15 修 01/02                  |
| 002   | MF shared 配置缺 urql/graphql/@edu/*            | ✅ 补全 7 项 singleton（react/react-dom/urql/graphql/@edu/ui-tokens/@edu/ui-components/@edu/hooks）         | ai15 修 02 §1.2                |
| 003   | switch-child 端点在 01/02 不一致                | ✅ GraphQL Mutation `switchChild(childId: ID!): SwitchChildPayload!`（走 GraphQL，对齐 ISSUE-001）          | ai15 修 01/02 + ai05 补 schema |
| 004   | 登录端点三方不一致                              | ✅ 统一为 `POST /api/v1/iam/login`（对齐 matrix.md §5）；登录走 REST，其余走 GraphQL                        | ai15 修 contract §2.3          |
| 005   | 02 §11.3 未决决策 #2 已由 ARB-001 裁决          | ✅ 移除未决项，改为"已裁决：见 ARB-001"                                                                     | ai15 修 02 §11.3               |
| 006   | contract §1.2 误标前端路由为 HTTP 端点          | ✅ §1.2 改为"无（parent-portal 是前端 Remote，不对外提供 HTTP API）"                                        | ai15 修 contract §1.2          |
| 007   | contract §1.6 MF 配置文件位置不一致             | ✅ 统一为 `apps/parent-portal/next.config.js`（对齐 02 + teacher-portal Shell）                             | ai15 修 contract §1.6          |
| 008   | contract §2.3 GraphQL 路径缺 v1                 | ✅ 统一为 `POST /api/v1/parent/graphql`（对齐 matrix.md §5）                                                | ai15 修 contract §2.3 + §2.4   |
| 009   | parent-bff GraphQL schema 是否含 switchChild    | ✅ parent-bff 提供 `switchChild` Mutation（后端记录选中子女用于审计），同时前端 Zustand + localStorage 缓存 | ai05 补 schema + ai15 前端实现 |
| 010   | iam GetChildrenByParent 缺失（P0 阻塞）         | ✅ ai06 P3 收尾前补全（I6 裁决）；补全前用 mock（固定 2 个孩子 student-001 + student-002）                  | ai06 补全 + ai15 mock          |
