Files
Edu/docs/architecture/issues/objections/student-portal_issue.md
SpecialX c6362f4b04
Some checks failed
CI / quality-ts (push) Failing after 53s
CI / quality-go (push) Failing after 7s
CI / quality-proto (push) Failing after 3s
CI / deploy (push) Has been skipped
docs(docs): 更新 issue 仲裁状态 + 生成集成测试阶段规划
- 14 个 issue.md 状态字段更新为"已裁决"
  - 对应 coord.md ARB-001~022 章节
  - 共 104 处状态字段更新
- 新增 integration-test-phase.md
  - 集成测试与部署验证阶段(P7)规划
  - 6 个批次任务分解
  - 8 条核心 E2E 链路定义
  - 验收标准和退出标准

Coord-AI
2026-07-10 22:05:37 +08:00

219 lines
18 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-portal 问题记录
> 负责人ai14
> 关联:[coord.md](../coord.md)、[contracts/student-portal_contract.md](../contracts/student-portal_contract.md)、[matrix.md](../matrix.md)
> 规则AI 遇到问题时在此追加条目coord 仲裁后更新状态
---
## §1 已有仲裁核查ARB-001 / ARB-002 对 student-portal 的影响)
### 1.1 ARB-001teacher-bff GraphQL schema 第一版)对 student-portal 的影响核查
| 裁决点 | 对 student-portal 的适用性 | ai14 落实方案 | 状态 |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------- |
| Schema 存放位置 | ✅ 适用原则一致。student-bff GraphQL schema 应存放于 `packages/shared-ts/contracts/graphql/student-bff.graphql`(集中管理,与 teacher-bff 同源) | ai14 在 contract.md §1.3 已标注预期路径;实际由 ai04 创建ai14 仅消费 | ⏳ 待 ai04 |
| P2 Query 范围 | ⚠️ 部分参考。ARB-001 是 teacher-bff 的 P2 范围student-portal 起步于 P3不在 P2因此 student-bff 直接以 P3 全量 Query 起步 | ai14 在 P3 直接消费 student-bff 全量 QuerycurrentUser/myClasses/myExams/myHomework/myGrades/myAttendance/studentDashboard | ✅ 已落实 |
| P2 Mutation 范围 | ⚠️ 部分参考。student-portal P3 起步即需要 submitHomework mutation作业提交是 P3 核心场景) | ai14 P3 即消费 submitHomework mutationai04 P3 必须提供 | ⏳ 待 ai04 |
| DataLoader 防 N+1 | ✅ 适用。student-bff 聚合多 gRPC 时(如 studentDashboard 聚合 iam+core-edu+data-ana必须使用 DataLoader | ai14 不直接实现,但依赖 student-bff 返回结构稳定(无 N+1 慢查询) | ⏳ 待 ai04 |
| 复杂度限制depth ≤ 7 | ✅ 适用。student-portal 发起的 GraphQL query 深度必须 ≤ 7 | ai14 在 [02-architecture-design.md §4.2](../../../apps/student-portal/docs/02-architecture-design.md) 已设计扁平 query | ✅ 已落实 |
| ActionState 信封 | ✅ 适用。student-bff 必须返回 ActionState 信封success/errors/data | ai14 在 GraphQL 请求层02 §3.2)已处理信封解包 + 降级字段识别 | ✅ 已落实 |
| 降级模式(方案 B | ✅ 适用。部分聚合失败时 success=true + data 内 `extensions.degraded: true` | ai14 在 [02 §18.2 降级策略矩阵](../../../apps/student-portal/docs/02-architecture-design.md) 已设计 12 个降级场景 | ✅ 已落实 |
| admin 命名空间 | ❌ 不适用。student-portal 不涉及 admin 命名空间 | - | - |
**核查结论**ARB-001 是 teacher-bff 的 P2 仲裁但其设计原则Schema 集中管理、ActionState 信封、降级模式方案 B、复杂度限制适用于所有 BFFstudent-portal 已在 02-architecture-design.md v2 中全面落实。
---
### 1.2 ARB-002MF Shell 暴露清单)对 student-portal 的影响核查
| 裁决点 | 对 student-portal 的适用性 | ai14 落实方案 | 状态 |
| ------------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| Shell 身份 | ✅ 适用。teacher-portal 是 MF Shellstudent-portal 是 P3 首个 Remote | ai14 在 [02 §3.2 MF 配置](../../../apps/student-portal/docs/02-architecture-design.md) 已声明 `remotes: { teacher: 'teacher@http://localhost:4000/_next/static/chunks/remoteEntry.js' }` | ✅ 已落实 |
| P3 首个 Remote | ✅ 适用。ARB-002 §2.3 明确 P3 首个 Remote 是 student-portal | ai14 P3 任务启动即接入 MF Remote | ✅ 已落实 |
| GraphQL client 归属 | ✅ 适用。Shell 暴露 GraphQLProviderstudent-portal 复用,**不重复创建 client** | ai14 在 [02 §3.2 GraphQL 请求层](../../../apps/student-portal/docs/02-architecture-design.md) 已使用 `useGraphQLClient()``@edu/hooks` 获取 | ✅ 已落实 |
| MF shared singleton 配置 | ✅ 适用。student-portal 必须将 react/react-dom/urql/graphql/@edu/* 声明为 singleton | ai14 在 [02 §3.2 next.config.js](../../../apps/student-portal/docs/02-architecture-design.md) 已声明全部 singleton | ✅ 已落实 |
| AppShell 复用 | ✅ 适用。student-portal 不重复实现 AppShell复用 Shell 暴露的 AppShell | ai14 在 02 §3.2 已设计 `<AppShell>` 包裹 + 学生端导航覆写 | ✅ 已落实 |
| useAuth / usePermission 复用 | ✅ 适用。student-portal 复用 Shell 暴露的 useAuth/usePermission | ai14 在 [01-understanding.md §6](../../../apps/student-portal/docs/01-understanding.md) 已声明权限校验走 usePermission | ✅ 已落实 |
| ErrorBoundary / Loading / Empty 复用 | ✅ 适用。student-portal 复用 Shell 暴露的共享 UI 组件 | ai14 在 02 §6 组件设计已使用 `@edu/ui-components` | ✅ 已落实 |
| feature flag | ✅ 适用。`NEXT_PUBLIC_MF_ENABLED` 控制是否走 MFP3 默认 true | ai14 在 02 §3.2 已设计独立壳回退MF 关闭时独立渲染) | ✅ 已落实 |
| 登录页 | ✅ 适用。P2 登录页由 Shell 独占student-portal 不实现登录页,未登录跳转 Shell `/login` | ai14 在 02 §3.2 已设计未认证 → 跳转 `window.location.href = 'http://localhost:4000/login?redirect=student'` | ✅ 已落实 |
**核查结论**ARB-002 是 student-portal 接入 MF 的直接依据ai14 已在 02-architecture-design.md v2 中全面落实。无异议。
---
### 1.3 ARB-001 / ARB-002 核查总结
| 仲裁 | 对 student-portal 的影响 | ai14 落实情况 | 异议 |
| ------- | ------------------------------------------------ | ------------- | ---- |
| ARB-001 | 设计原则适用GraphQL + ActionState + 降级模式) | ✅ 已落实 | 无 |
| ARB-002 | 直接适用P3 首个 Remote + Shell 暴露清单) | ✅ 已落实 | 无 |
> **ai14 声明**ARB-001 / ARB-002 已在 02-architecture-design.md v2 中全面落实,无需新增仲裁。
---
## §2 新提请异议(待 coord 仲裁)
### ISSUE-014-01-ai14GraphQL endpoint 路径不一致(`/api/student/graphql` vs `/api/v1/student/graphql`
- **提请方**ai14
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**
- `student-portal_contract.md` §2.3 当前写 `POST /api/student/graphql`(无 `/v1/` 前缀)
- `matrix.md` §5 HTTP 接口矩阵明确写 `api-gateway` 反向代理 `student-portal` 的路径是 `/api/v1/student/*`
- `01-understanding.md` v2 §3.1 和 `02-architecture-design.md` v2 §4.1 已统一为 `POST /api/v1/student/graphql`
- 三处不一致,需要 coord 仲裁统一为 `/api/v1/student/graphql`(与 matrix.md §5 对齐,与 teacher-portal `/api/v1/teacher/graphql` 保持命名一致性)
- **建议方案**
- 统一为 `POST /api/v1/student/graphql`
- 由 ai01api-gateway确认路由`/api/v1/student/*``student-bff:3009/*`(即 `/api/v1/student/graphql``student-bff:3009/graphql`
- 由 ai04student-bff确认 GraphQL endpoint 路径为 `POST /graphql`(与 teacher-bff 一致)
- **状态**:已裁决(见 coord.md §21
---
### ISSUE-014-02-ai14student-bff GraphQL schema 文件存放位置不一致(集中管理 vs 应用内管理)
- **提请方**ai14
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**
- ARB-001 §1.3 关键裁决明确teacher-bff GraphQL schema 存放于 `packages/shared-ts/contracts/graphql/teacher-bff.graphql`(集中管理,总裁裁决 §2.17 SDL-first + 集中管理)
- `student-bff_contract.md` §1.3 写:`apps/student-bff/src/schema/*.graphql`(应用内管理,与 ARB-001 原则不一致)
- `matrix.md` §3 GraphQL 接口提供方矩阵写:`packages/shared-ts/contracts/graphql/student-bff.graphql`(与 ARB-001 一致)
- 两处不一致,需要 coord 仲裁统一
- **建议方案**
- 统一为 `packages/shared-ts/contracts/graphql/student-bff.graphql`(与 ARB-001 原则对齐,集中管理便于前端 codegen
- ai14 在 student-portal 端使用 `graphql-codegen` 从该 schema 生成 TypeScript 类型
- 由 ai04student-bff创建该 schema 文件并维护
- **状态**:已裁决(见 coord.md §21
---
### ISSUE-014-03-ai14考试作答页全屏策略与防作弊检测边界
- **提请方**ai14
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**
- student-portal 02-architecture-design.md §14 设计了防作弊检测visibilitychange/copy/paste/fullscreen/contextmenu但未明确以下边界
1. **全屏 API 强制策略**是否强制全屏Fullscreen API退出全屏是否触发警告/记录?
2. **离开页面策略**visibilitychange hidden 触发时,是仅记录还是自动提交?
3. **多标签检测**BroadcastChannel 检测到多标签时,是警告还是阻止作答?
4. **防作弊事件上报**:前端采集的防作弊事件如何上报?走 student-bff GraphQL mutation 还是 push-gateway WebSocket
- 这些决策影响 ai04student-bff是否需要提供 `recordExamViolation` mutation以及 ai08core-edu是否需要存储违规记录
- **建议方案**
- **全屏策略**P3 推荐但不强制(提示"建议全屏作答"P4 评估是否升级为强制(基于教师反馈)
- **离开页面策略**visibilitychange hidden 触发时仅记录(不自动提交),累计 3 次警告后教师端可见
- **多标签检测**:警告 + 记录,不阻止作答(避免误伤合法场景如查词典)
- **防作弊事件上报**:走 student-bff GraphQL mutation `recordExamViolation(examId, type, payload)`,由 ai04 在 P3 提供
- **状态**:已裁决(见 coord.md §21
---
### ISSUE-014-04-ai14主观题粘贴策略防作弊 vs 学生体验)
- **提请方**ai14
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**
- 02-architecture-design.md §14 防作弊检测包含 `paste` 事件拦截,但学生作答主观题时可能需要粘贴(如从草稿本粘贴长文本)
- 策略不明确:全部禁止粘贴?仅主观题允许?仅客观题禁止?
- 影响学生体验和防作弊效果平衡
- **建议方案**
- **客观题**:禁止粘贴(防作弊优先)
- **主观题(简答/论述)**:允许粘贴,但记录粘贴事件 + 粘贴内容长度,教师端批改时可见
- **作文题**:允许粘贴(学生体验优先),不记录
- 由 ai04student-bff在 P3 提供 `recordPasteEvent` mutation或复用 ISSUE-014-03 的 `recordExamViolation`type=`PASTE`
- **状态**:已裁决(见 coord.md §21
---
### ISSUE-014-05-ai14作业附件上传协议GraphQL mutation vs REST multipart
- **提请方**ai14
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**
- 学生提交作业时可能需要上传附件(图片/PDF/文档GraphQL mutation 不适合处理大文件上传multipart/form-data
- 当前 contract.md 未明确附件上传协议
- 选项:
- A. 走 api-gateway REST 端点(`POST /api/v1/student/upload` → 对象存储),返回 URL再走 GraphQL mutation 提交 URL
- B. 走 student-bff GraphQL multipartgraphql-upload需要 ai04 支持)
- C. 走独立上传服务(如 push-gateway 扩展或新建 upload-service
- **建议方案**
- **推荐 A**:走 api-gateway REST `POST /api/v1/student/upload` → 对象存储MinIO/OSS返回 signed URL再走 GraphQL `submitHomework(attachmentUrls: [String!])` mutation 提交
- 理由GraphQL 不适合大文件传输REST + 对象存储是业界通用方案api-gateway 已有 JWT 鉴权
- 由 ai01api-gateway确认是否提供 `/api/v1/student/upload` 路由,由 ai04student-bff确认 `submitHomework` mutation 是否接受 `attachmentUrls` 字段
- **状态**:已裁决(见 coord.md §21
---
### ISSUE-014-06-ai14考试延长/题目重排等实时事件命名未确认
- **提请方**ai14
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**
- student-portal 02-architecture-design.md §16 设计了 WebSocket 实时通知,但以下事件命名未在 matrix.md §4 Kafka 事件矩阵中确认:
1. **考试延长**(教师延长考试时间):事件名 `ExamExtended`?还是 `ExamUpdated`?由 ai08core-edu发布
2. **题目重排**(教师重排题目顺序):事件名 `ExamQuestionReordered`?是否需要前端实时重排?
3. **考试强制提交**(教师强制收卷):事件名 `ExamForceSubmitted`?前端收到后立即提交?
- 这些事件影响 student-portal 考试作答页的实时响应逻辑
- **建议方案**
- **考试延长**ai08core-edu发布 `ExamExtended` 事件到 `edu.exam.events` topicmsgai10消费后通过 push-gateway 推送student-portal 收到后更新倒计时
- **题目重排**P3 不实现题目顺序固定P4 评估是否需要实时重排
- **考试强制提交**ai08 发布 `ExamForceSubmitted` 事件student-portal 收到后立即触发提交流程
- 由 ai08core-edu确认事件命名由 ai10msg确认推送路径
- **状态**:已裁决(见 coord.md §21
---
### ISSUE-014-07-ai14学生端 DataScope L0 边界(仅能查看自己数据)的强制执行层
- **提请方**ai14
- **日期**2026-07-10
- **类型**:契约不明确
- **描述**
- 01-understanding.md §8 和 02-architecture-design.md §6 声明学生 DataScope L0仅能查看自己数据
- 但强制执行层不明确:
- A. student-bff 在 Resolver 层基于 JWT 的 `x-user-id` 强制过滤(推荐,前端无法绕过)
- B. student-portal 在 GraphQL query 中显式传 `studentId`(不安全,前端可篡改)
- 当前 02-architecture-design.md §4.2 的 GraphQL query 设计中,部分 query 显式传 `studentId`(如 `myClasses(studentId: ID!)`),这与 L0 强制执行矛盾
- **建议方案**
- **统一为方案 A**student-bff 在 Resolver 层从 JWT `x-user-id` 提取 studentId强制过滤前端 query 不传 `studentId` 参数
- ai14 修改 02-architecture-design.md §4.2 的 GraphQL query 定义,移除 `studentId` 参数(如 `myClasses` 改为无参 query
- 由 ai04student-bff确认所有学生端 Query 均从 JWT 提取 studentId不接受前端传入
- **状态**:已裁决(见 coord.md §21
---
## §3 异议状态汇总
| 编号 | 类型 | 标题 | 状态 |
| ------------ | ---------- | ------------------------------------------------------ | ------ |
| ISSUE-014-01 | 契约不明确 | GraphQL endpoint 路径不一致 | 已裁决 |
| ISSUE-014-02 | 契约不明确 | student-bff GraphQL schema 存放位置不一致 | 已裁决 |
| ISSUE-014-03 | 契约不明确 | 考试作答页全屏策略与防作弊检测边界 | 已裁决 |
| ISSUE-014-04 | 契约不明确 | 主观题粘贴策略(防作弊 vs 学生体验) | 已裁决 |
| ISSUE-014-05 | 契约不明确 | 作业附件上传协议GraphQL mutation vs REST multipart | 已裁决 |
| ISSUE-014-06 | 契约不明确 | 考试延长/题目重排等实时事件命名未确认 | 已裁决 |
| ISSUE-014-07 | 契约不明确 | 学生端 DataScope L0 边界的强制执行层 | 已裁决 |
---
<!--
追加条目格式:
### ISSUE-[编号]-[AI标识][标题]
- **提请方**aiXX
- **日期**YYYY-MM-DD
- **类型**:契约不明确 / 工作量超批 / 前置依赖缺失 / 编号冲突 / 其他
- **描述**[详细描述问题]
- **建议方案**[AI 的建议]
- **状态**:已裁决(见 coord.md §X
-->