Files
Edu/docs/architecture/issues/coord.md
SpecialX c179af64a6 docs(docs): coord 完成 15 模块 issue 仲裁与基础设施同步
coord.md 新增 ARB-019/020/021 三章仲裁章节,修正 ARB-001。

- coord.md: 新增 ARB-019/020/021(student/parent/admin-portal 24 项)
- coord.md: 修正 ARB-001(admin P2 预留/schema 文件名/classes 数据源)
- 004 §4: 依赖图加 PBFF→DataAna+Msg
- 004 §7.2: push-gateway→Redis 软失败标注
- 004 §11.4: 错误码前缀矩阵(11 服务+i18n key)
- 004 §11.5: ActionState 信封规范(降级模式方案 B)
- matrix §1: 依赖矩阵加 PBFF 边
- matrix §2: 移除 api-gateway 为 iam gRPC 消费方
- matrix §4: admin-portal→teacher-bff
- matrix §5: 移除 /sse+鉴权头统一
- matrix §6: 错误码表补 i18n key 列
- 15 个 issue.md: 仲裁结论回写
- push-gateway_contract: 移除 /sse+鉴权头改 X-Internal-Token
- packages/contracts: 新建包 ADMIN_* 权限点常量

AI: coord
2026-07-10 16:30:51 +08:00

1635 lines
124 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.
# coord 仲裁结果汇总
> 维护者coord协调 AI
> 维护规则:各 AI 在 `objections/[模块名]_issue.md` 提请异议 → coord 审阅 → 在本文件写入仲裁结果
> 关联文档:[president-final-rulings.md](../president-final-rulings.md)、[ai-work-orchestration.md](../ai-work-orchestration.md)、[workline.md](./workline.md)、[matrix.md](./matrix.md)
---
## 仲裁记录索引
| 编号 | 日期 | 提请方 | 主题 | 状态 | 仲裁章节 |
| ------- | ---------- | --------------------- | ------------------------------------------------------------------------ | --------- | -------- |
| ARB-001 | 2026-07-09 | coord全并行启动前 | teacher-bff GraphQL schema 第一版 | ✅ 已裁决 | §1 |
| ARB-002 | 2026-07-09 | coord全并行启动前 | MF Shell 暴露清单 | ✅ 已裁决 | §2 |
| ARB-003 | 2026-07-10 | ai06 | iam 模块 7 项 ISSUE 仲裁 | ✅ 已裁决 | §3 |
| ARB-004 | 2026-07-10 | ai08 | core-edu 模块 7 项 ISSUE 仲裁 | ✅ 已裁决 | §4 |
| ARB-005 | 2026-07-10 | ai09 | content 模块 10 项 ISSUE 仲裁 | ✅ 已裁决 | §5 |
| ARB-006 | 2026-07-10 | coord跨模块 | events.proto 补全(跨 iam/core-edu/content | ✅ 已裁决 | §6 |
| ARB-007 | 2026-07-10 | coord跨模块 | proto 契约补全汇总iam.proto + core_edu.proto | ✅ 已裁决 | §7 |
| ARB-008 | 2026-07-10 | ai10 | msg 模块 15 项 ISSUE 仲裁 | ✅ 已裁决 | §10 |
| ARB-009 | 2026-07-10 | ai11 | data-ana 模块 6 项 ISSUE 仲裁 | ✅ 已裁决 | §11 |
| ARB-010 | 2026-07-10 | ai12 | ai 模块 9 项 ISSUE 仲裁 | ✅ 已裁决 | §12 |
| ARB-011 | 2026-07-10 | coord跨模块 | events.proto 扩展补全msg/data-ana/ai message+ proto package 命名统一 | ✅ 已裁决 | §13 |
| ARB-012 | 2026-07-10 | coord跨模块 | analytics.proto + ai.proto 补全 | ✅ 已裁决 | §14 |
| ARB-013 | 2026-07-10 | coord跨模块 | Kafka topic 命名统一裁决(跨全模块) | ✅ 已裁决 | §15 |
| ARB-014 | 2026-07-10 | ai01 | api-gateway 模块 4 项内联 ISSUE 仲裁 | ✅ 已裁决 | §16 |
| ARB-015 | 2026-07-10 | ai02 | push-gateway 模块 7 项 ISSUE 仲裁 | ✅ 已裁决 | §17 |
| ARB-016 | 2026-07-10 | ai03 | teacher-bff 模块 3 项 ISSUE 仲裁 | ✅ 已裁决 | §18 |
| ARB-017 | 2026-07-10 | ai04 | student-bff 模块 4 项新 ISSUE 仲裁 | ✅ 已裁决 | §19 |
| ARB-018 | 2026-07-10 | ai05 | parent-bff 模块 10 项 ISSUE 仲裁 | ✅ 已裁决 | §20 |
| ARB-019 | 2026-07-10 | ai14 | student-portal 模块 7 项 ISSUE 仲裁 | ✅ 已裁决 | §21 |
| ARB-020 | 2026-07-10 | ai15 | parent-portal 模块 10 项 ISSUE 仲裁 | ✅ 已裁决 | §22 |
| ARB-021 | 2026-07-10 | ai16 | admin-portal 模块 7 项 ISSUE 仲裁 | ✅ 已裁决 | §23 |
---
## §1 ARB-001teacher-bff GraphQL schema 第一版
### 1.1 背景
全并行启动前,需仲裁 teacher-bff GraphQL schema 第一版,作为 ai03teacher-bff和 ai13teacher-portal的共同契约。
数据源ai03 的 [02-architecture-design.md §5](../../services/teacher-bff/docs/02-architecture-design.md#L503) 提供了目标态 schemaP4但 P2 只需 Must Have 子集。
### 1.2 仲裁结论
**P2 第一版 schema 范围**Must Have对应 ai03 P2 工作量分级 Must Have 13 项):
```graphql
# ============ P2 第一版 schema ============
# 存放位置packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql
# 仲裁原则:仅包含 P2 可实现的 Queryiam 已就绪Mutation 延后到 P3
# 修订ARB-016 §18admin 命名空间 P2 预留 schema 占位(总裁 §5.1 + §7.3 裁决优先级 president > coord
# 修订ARB-016 §18schema 文件名统一为 <bff-name>.schema.graphql总裁 §2.17
scalar DateTime
enum DataScope {
SELF
CLASS
GRADE
SCHOOL
SUBJECT
ALL
}
enum ExamStatus {
DRAFT
PUBLISHED
IN_PROGRESS
GRADING
SCORED
ARCHIVED
}
enum SubmissionStatus {
NOT_SUBMITTED
SUBMITTED
GRADED
}
type User {
id: ID!
email: String!
name: String!
roles: [String!]!
dataScope: DataScope!
}
type ViewportItem {
key: String!
label: String!
route: String!
icon: String
sortOrder: String!
requiredPermission: String
}
type Class {
id: ID!
name: String!
gradeId: String!
studentCount: Int!
}
type DashboardStats {
totalExams: Int!
pendingGrading: Int!
todayHomework: Int!
}
type DashboardData {
user: User!
classes: [Class!]!
viewports: [ViewportItem!]!
stats: DashboardStats!
}
# ============ QueryP2 仅读,无 Mutation ============
type Query {
# 仪表盘聚合并行iam.me + iam.viewports + iam.permissions + iam.classesByTeacher
dashboard: DashboardData!
# 视口配置(导航)
viewports: [ViewportItem!]!
# 当前用户信息
me: User!
# 班级列表(按教师 dataScope 过滤,数据来自 iam gRPC总裁 §3.5
classes: [Class!]!
class(id: ID!): Class
}
# ============ P2 不包含P3+ 扩展) ============
# - exams / homework / grades Query → P3core-edu 就绪后)
# - classPerformance / studentWeakness / learningTrend → P4data-ana 就绪后)
# - notifications → P5msg 就绪后)
# - 所有 Mutation → P3+
# - Subscription → P6+ 评估
# ============ admin 命名空间P2 预留 schema 占位P6 实现) ============
# 总裁 §5.1admin-portal 复用 teacher-bffadmin 命名空间 P2 预留 schema 占位
# P2 仅声明类型骨架Resolver 返 nullP6 实现ARB-021 ISSUE-005
# 详见 ARB-021 §23.4 admin 命名空间 schema 清单
extend type Query {
# adminUsers / adminRoles / adminPermissions / adminViewports
# adminOrganization / adminClasses / adminTeachers / adminStudents
# auditLogs / adminDashboard
# P6 实现P2 仅占位)
}
extend type Mutation {
# createUser / updateUser / deleteUser / toggleUserStatus
# createRole / updateRolePermissions / updateViewport
# P6 实现P2 仅占位)
}
```
### 1.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ----------------- | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Schema 存放位置 | `packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql` | 总裁裁决 §2.17 SDL-first + 集中管理 |
| schema 文件名格式 | `<bff-name>.schema.graphql`(统一格式,对齐 student-bff/parent-bff | 总裁裁决 §2.17 + ARB-016 §18.3 |
| P2 Query 范围 | dashboard / viewports / me / classes / class5 个) | 仅依赖 iamP2 就绪classes 数据从 iam gRPC 获取(总裁 §3.5 |
| P2 Mutation 范围 | **无**P2 纯读) | Mutation 依赖 core-eduP3P2 无下游可写 |
| DataLoader | dashboard 内 classes 列表用 DataLoader | N+1 防御ai03 §5.1 第 4 条) |
| 复杂度限制 | depth ≤ 7cost ≤ 1000 | ai03 §5.1 第 5 条 |
| admin 命名空间 | **P2 预留** schema 占位(声明 admin Query/Mutation 类型骨架Resolver 返 nullP6 实现 | 总裁裁决 §5.1 + §7.3(裁决优先级 president > coord修正原 ARB-001 "P2 不包含" |
| DataScope 枚举 | SELF / CLASS / GRADE / SCHOOL / SUBJECT / ALLSUBJECT 替代 DISTRICT | coord DataScope 6 级统一 |
| 错误响应 | ActionState 信封success/errors/data | coord-final-decisions F9 |
| 降级模式 | success=true + error=null + data 内 degraded 字段 | 总裁裁决 §3.4 方案 B |
> **修订记录**ARB-016 §182026-07-10
>
> 1. admin 命名空间由 "P2 不包含" 修正为 "P2 预留 schema 占位"(总裁 §5.1 + §7.3 优先级 president > coord
> 2. schema 文件名由 `teacher-bff.graphql` 修正为 `teacher-bff.schema.graphql`(统一 `<bff-name>.schema.graphql` 格式,总裁 §2.17
> 3. classes 数据来源明确为 iam gRPC总裁 §3.5,非 core-edu
### 1.4 ai03 执行项
1.`packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql` 创建 P2 第一版 schema 文件
2. teacher-bff 实现 Yoga GraphQL endpoint`POST /graphql`
3. 实现 5 个 Query Resolverdashboard / viewports / me / classes / class
4. dashboard Resolver 并行调用 iam3 RPC+ iam.classesByTeacher1 RPC用 DataLoader 防御 N+1总裁 §3.5classes 数据从 iam gRPC 获取)
5. 实现 ActionState 信封 + 降级模式(方案 B
6. P2 预留 admin 命名空间 schema 占位声明类型骨架Resolver 返 nullP6 实现见 ARB-021 §23.4
### 1.5 ai13 执行项
1. teacher-portal Shell 暴露 `GraphQLProvider`urql client 单例)
2. 使用 `useGraphQLClient()` 从 packages/hooks 获取 client
3. P2 页面dashboard / classes通过 GraphQL query 拉取数据
4. **不调用 REST 端点**除登录外P2 起 all-in GraphQL
---
## §2 ARB-002MF Shell 暴露清单
### 2.1 背景
全并行启动前,需仲裁 teacher-portal 作为 MF Shell 暴露哪些模块给 Remotestudent/parent/admin作为 ai13 的实现依据。
数据源ai13 的 [03-long-term-architecture.md §1.4](../../apps/teacher-portal/docs/03-long-term-architecture.md) 提供了 GraphQL client 单例设计。
### 2.2 仲裁结论
**P2 第一版 MF Shell 暴露清单**
```typescript
// teacher-portal/next.config.js — NextFederationPlugin exposes
exposes: {
// 1. AppShell布局 + 导航 + 认证守卫)
'./AppShell': './src/components/AppShell.tsx',
// 2. GraphQLProviderurql client 单例,总裁 §2.17 方案 A
'./GraphQLProvider': './src/app/providers.tsx',
// 3. 共享 hooks
'./useAuth': './packages/hooks/src/use-auth.ts',
'./usePermission': './packages/hooks/src/use-permission.ts',
'./useGraphQLClient': './packages/hooks/src/use-graphql-client.ts',
// 4. 共享 UI 组件
'./ErrorBoundary': './packages/ui-components/src/error-boundary.tsx',
'./Loading': './packages/ui-components/src/loading.tsx',
'./Empty': './packages/ui-components/src/empty.tsx',
'./RequirePermission': './packages/ui-components/src/require-permission.tsx',
}
```
**MF sharedsingleton配置**
```typescript
shared: {
react: { singleton: true, requiredVersion: '^18.3.0' },
'react-dom': { singleton: true, requiredVersion: '^18.3.0' },
urql: { singleton: true, requiredVersion: '^2.2.0' },
graphql: { singleton: true, requiredVersion: '^16.8.0' },
'@edu/ui-tokens': { singleton: true },
'@edu/ui-components': { singleton: true },
'@edu/hooks': { singleton: true },
}
```
### 2.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ------------------- | ---------------------------------------------- | --------------------------- |
| Shell 身份 | teacher-portal 是 MF Shell非 Remote | 总裁裁决 §2.17 + ai13 §1.3 |
| P2 Remote 数量 | **0**P2 暂无 Remote仅配置 exposes/shared | ai13 §1.3 绞杀者模式 step 3 |
| P3 首个 Remote | student-portal | ai13 §1.3 step 4 |
| GraphQL client 归属 | Shell 暴露 GraphQLProviderRemote 复用 | 总裁 §2.17 方案 A |
| MF shared singleton | react / react-dom / urql / graphql / @edu/* | 避免多实例 + 缓存不一致 |
| AppShell 暴露 | 是Remote 复用布局 + 导航 + 认证守卫) | ai13 §1.3 |
| feature flag | `NEXT_PUBLIC_MF_ENABLED=false`P2 默认关) | ai13 §1.3 回退策略 |
| 登录页 | P2 不走 MFShell 独占 `/login` | 登录是认证前提MF 依赖认证 |
### 2.4 ai13 执行项
1. teacher-portal `next.config.js` 添加 NextFederationPluginexposes + shared**无 remotes**
2. 创建 `src/app/providers.tsx`GraphQLProvider 包裹)
3. AppShell 改造:从 REST `/api/v1/teacher/viewports` 切换为 GraphQL query `viewports`
4. P2 页面dashboard / classes全部用 GraphQL
5. feature flag `NEXT_PUBLIC_MF_ENABLED=false`P2 默认单体路由)
### 2.5 ai03 执行项(联动)
1. teacher-bff 暴露 `POST /graphql` endpoint
2. 提供GraphQL playground仅开发环境
---
## §3 ARB-003iam 模块 7 项 ISSUE 仲裁
### 3.1 背景
ai06 在 [iam_issue.md](./objections/iam_issue.md) §2 提请 7 项异议涉及文档回写、events.proto 缺失、Topic 命名不一致、DataScope 枚举冲突、iam.proto 未补全、AI 身份署名错误、双入口策略冲突。coord 对照 [iam_contract.md](./contracts/iam_contract.md)v1.0,已含双入口策略 + 12 RPC + REST 端点清单)逐条仲裁。
### 3.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | --------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| 001 | 01/02 文档未回写 I1-I8 裁决 | ✅ 支持 ai06 方案3 个工作日内回写 01/02删除全部过渡方案对齐 contract.md v1.0 | ai06 |
| 002 | events.proto 缺 UserEvent/RoleEvent/AuditEvent | ✅ coord 批次 0 补全(见 §6 ARB-006 统一处理) | coord |
| 003 | Topic 命名三方不一致edu.identity.* vs edu.iam.* | ✅ 统一 `edu.iam.*` 域名 + 聚合 topic 风格 | coord 修 004 + matrix.md |
| 004 | DataScope 枚举三方不一致 | ✅ 采用 president §3.2 P2.2 方案ALL/SCHOOL/GRADE/CLASS/SUBJECT/SELFSUBJECT 替代 DISTRICT | coord 修 004 + ai06 修源码 + coord 修 ARB-001 GraphQL schema |
| 005 | iam.proto 仅 4 RPC未补全至 12 RPC | ✅ coord 批次 0 补全(见 §7 ARB-007 统一处理) | coord |
| 006 | 01/02 文档 AI 身份署名错误 | ✅ 与 ISSUE-001 一并回写,署名改为 ai06 | ai06 |
| 007 | contract.md §1.2 与双入口策略冲突 | ✅ contract.md 已修正为双入口策略REST + gRPCai06 回写 02 文档时对齐 | ai06 |
### 3.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ----------------- | --------------------------------------------------------- | -------------------------------------------------------------- |
| Topic 域名 | `edu.iam.*`(服务名 iam非 identity | G16 规则 `edu.<domain>.<aggregate>.<action>`domain=服务名 |
| Topic 粒度 | 聚合 topic`edu.iam.user.events` 含多 action | 与 events.proto ClassEvent 模式一致,减少 topic 数量 |
| DataScope 枚举 | ALL/SCHOOL/GRADE/CLASS/SUBJECT/SELF6 级) | president §3.2 P2.2SUBJECT 替代 DISTRICTK12 学科级更实用) |
| 双入口策略 | REST `/iam/v1/*` 供 gateway 透传 + gRPC 50052 供 BFF 聚合 | president §2.16 |
| iam.proto 补全 | 12 RPCcontract.md §1.1 已定义) | coord-final-decisions §5.1 + president §6 批次 0 |
| events.proto 补全 | UserEvent/RoleEvent/AuditEvent + schema_version 字段 | coord-final-decisions §5.1 + president §5.5 |
| 004 §7.2 修正 | `edu.identity.*``edu.iam.*`,改为聚合 topic 风格 | 与 matrix.md §4 / iam_contract.md §1.4 统一 |
### 3.4 ai06 执行项
1. 回写 iam 01/02 文档3 个工作日内):
- 删除全部过渡方案P2 仅 REST / 自建 Outbox / PermissionGuard 待改造 / AuthMiddleware P2 不注册 / iam_parent_student_relations / 无 /v1 前缀 / HTTP 调用 iam
- 对齐 contract.md v1.012 RPC + 双入口 + REST `/iam/v1/*` + gRPC 50052
- 署名从 ai02 改为 ai06
- 02 文档 §3.1.2 表名改为 `iam_student_guardians`I6 裁决)
- 02 文档 §8.1 决策点 5 改为"P2 即启用 gRPC 50052"I1 裁决)
- 02 文档 §8.1 决策点 4 改为"使用 shared-ts Outbox 工具包"I2 裁决)
- 02 文档 §8.1 决策点 9 改为"P2 即 DB 驱动 + Redis 缓存"I3 裁决)
- 02 文档 §1.1/§1.2/§8.1 决策点 10 改为"P2 即注册 AuthMiddleware"I4 裁决)
- 02 文档 §4.1 REST API 加 `/v1` 前缀I7 裁决)
2. 修改源码 iam.schema.ts DataScope 枚举DISTRICT → SUBJECTISSUE-004
3. 实现源码 PermissionGuard DB 驱动 + Redis 缓存I3 裁决)
4. 实现源码 AuthMiddleware 注册I4 裁决)
5. 实现源码 RS256 密钥I5 裁决,本地文件 IAM_PRIVATE_KEY_PATH / IAM_PUBLIC_KEY_PATH
6. 实现源码 iam_student_guardians 表 + GetChildrenByParent RPC + GET /iam/v1/childrenI6 裁决)
### 3.5 coord 执行项
1. 补全 iam.proto 至 12 RPCARB-007批次 0
2. 补全 events.proto UserEvent/RoleEvent/AuditEvent + schema_versionARB-006批次 0
3. 修正 004 §7.2`edu.identity.*``edu.iam.*`,改为聚合 topic 风格
4. 修正 004 §5.3 表DataScope 枚举 DISTRICT → SUBJECT行 505 语义命名与枚举表对齐
5. 修正 ARB-001 GraphQL schema DataScope 枚举:去掉 DISTRICT加 SUBJECT
6. 修正 matrix.md §4iam topic 已为 `edu.iam.*`(核查无需改);补 DataScope 枚举说明
---
## §4 ARB-004core-edu 模块 7 项 ISSUE 仲裁
### 4.1 背景
ai08 在 [core-edu_issue.md](./objections/core-edu_issue.md) 提请 7 项异议,涉及 proto 实际状态与仲裁声称不符、events.proto 未同步、状态命名跨模块不一致、class.transferred topic 不一致、RPC 数量统计口径冲突、7 项设计决策未仲裁、01 文档审计待核对项。coord 对照 [core-edu_contract.md](./contracts/core-edu_contract.md)(已更新为 P3 目标态 27 RPC逐条仲裁。
### 4.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| 001 | core_edu.proto 实际状态与仲裁声称不符 | ✅ coord 批次 0 补全至 5 Service 27 RPC见 §7 ARB-007 | coord |
| 002 | events.proto 未同步 topic 命名仲裁 | ✅ coord 批次 0 补全(见 §6 ARB-006AttendanceEvent + schema_version + edu.teaching.* 注释) | coord |
| 003 | 考试/作业状态命名跨模块不一致 | ✅ 采用 ai08 方案 A统一用 `graded`(去掉 `SCORED`submissions 统一为 `not_submitted/submitted/graded` | ai08 修源码 + coord 修 ARB-001 GraphQL schema |
| 004 | class.transferred 事件 topic 三处不一致 | ✅ 统一为 `edu.teaching.class.transferred` | coord 修 matrix.md + ai08 修文档 |
| 005 | RPC 数量统计口径不一致 | ✅ 统一为 P3 全量 27 RPCClassService 4 + ExamService 8 + HomeworkService 5 + GradeService 6 + AttendanceService 4 | coord 修 matrix.md + ai08 修文档 |
| 006 | 7 项设计决策待仲裁 | ✅ 全部采用 ai08 倾向方案(见 §4.4 | ai08 |
| 007 | 01 文档审计表"待核对"项 | ✅ 3 项纳入 P3 验收硬性标准 | ai08 |
### 4.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| proto 补全范围 | 5 Service 27 RPC含 ClassService + AttendanceService + P3 新增 5 RPC + Exam/Homework/Grade message 补字段 + SubmitHomeworkRequest 补 answers | ISSUE-001 建议 |
| Topic 命名 | 统一 `edu.teaching.<aggregate>.<action>`(含 class.transferred | coord-cross-review §3.1 |
| 聚合 topic | core-edu 采用具体动作 topic`edu.teaching.exam.created` 等独立 topic非聚合 | 与 iam 聚合 topic 不同core-edu 事件量大,独立 topic 利于分区与消费隔离 |
| ExamStatus | draft/published/in_progress/grading/graded/archived/cancelled小写 | 统一为 graded去掉 SCORED |
| SubmissionStatus | not_submitted/submitted/gradedexam + homework 一致) | 统一初始状态为 not_submitted |
| GraphQL 枚举映射 | DRAFT/PUBLISHED/IN_PROGRESS/GRADING/GRADED/ARCHIVED/CANCELLEDNOT_SUBMITTED/SUBMITTED/GRADED | 大写映射,去掉 SCORED |
| RPC 统计口径 | 27 RPCP3 全量) | ClassService 4 + ExamService 8 + HomeworkService 5 + GradeService 6 + AttendanceService 4 |
> **注**core-edu topic 策略采用"具体动作 topic"`edu.teaching.exam.created` 等),与 iam/content 的"聚合 topic"`edu.iam.user.events` / `edu.content.knowledge_point.events`不同。原因core-edu 事件量大12 个事件类型),独立 topic 利于 Kafka 分区与消费者隔离iam/content 事件量小,聚合 topic 减少元数据压力。此为 coord 裁决的策略差异,非矛盾。
### 4.4 ISSUE-006 七项设计决策仲裁
| # | 决策点 | 仲裁结论 | ai08 倾向 |
| --- | ------------------- | -------------------------------------------------- | --------- |
| 1 | classes 合并时机 | ✅ (a) P3 初期合并 | (a) |
| 2 | room_id | ✅ (b) 仅预留字段 | (b) |
| 3 | scope 优先级 | ✅ (a) class > subject > school | (a) |
| 4 | grace_period | ✅ (b) 300 秒schema 默认值改为 `.default(300)` | (b) |
| 5 | schema 校验 | ✅ (b) 仅文档约束P3 不强制) | (b) |
| 6 | exam.submitted 事件 | ✅ (b) 仅含 submission_id | (b) |
| 7 | archived 考试 | ✅ (b) P3 仅软删除 | (b) |
### 4.5 ai08 执行项
1. 修改 core-edu 01/02 文档:
- 01 §L48 补"ClassService 也缺失"
- 02 §4.2 对齐 27 RPC补 ClassService 4 + AttendanceService 4 + P3 新增 5 RPC + message 字段)
- 02 §5.1 TOPIC_MAP 对齐 `edu.teaching.*` 命名(具体动作 topic
- 02 §13.3 七项决策按 §4.4 仲裁结论更新(决策 #4 schema `.default(300)`
- class.transferred topic 统一为 `edu.teaching.class.transferred`
2. 修改源码 status 字段值exam `graded`(非 `scored`submissions 统一 `not_submitted`
3. P3 实施时补齐 Dockerfile 多阶段 / ActionState traceId / 权限装饰器覆盖ISSUE-007 验收标准)
### 4.6 coord 执行项
1. 补全 core_edu.proto 至 5 Service 27 RPCARB-007批次 0
2. 补全 events.proto AttendanceEvent + schema_version + edu.teaching.* 注释ARB-006批次 0
3. 修正 coord-cross-review.md L312"✅ 已补全" → "⏳ 待 coord 补全ARB-007"
4. 修正 matrix.md §2core-edu 22 RPC → 27 RPC
5. 修正 matrix.md §4class.transferred topic 统一为 `edu.teaching.class.transferred`
6. 修正 ARB-001 GraphQL schemaExamStatus 去掉 SCORED 加 CANCELLEDSubmissionStatus 去掉 IN_PROGRESS如有确认 NOT_SUBMITTED/SUBMITTED/GRADED
7. 修正 core-edu_contract.md §2.2UserEvent topic 从 `edu.identity.user.*` 改为 `edu.iam.user.events`(与 iam ISSUE-003 仲裁一致,聚合 topic 风格)
---
## §5 ARB-005content 模块 10 项 ISSUE 仲裁
### 5.1 背景
ai09 在 [content_issue.md](./objections/content_issue.md) 提请 10 项异议,涉及 REST 端点设计不一致、事件 topic 命名策略冲突、Textbook/Chapter 事件遗漏、RPC 数量三方不一致、core-edu 失效事件无定义、文档 push main 冲突、created_by 迁移风险、缓存/API 版本化缺失、schema 字段缺失、Sync Worker 链路。coord 对照 [content_contract.md](./contracts/content_contract.md)v1.1,已更新为 21 RPC + 4 聚合 topic逐条仲裁。
### 5.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| 001 | REST 端点设计与实现不一致 | ✅ P4 重构时统一为 query 参数风格 + 补 DELETE prerequisite 端点;允许 API 路径变更BFF 走 GraphQL 解耦) | ai09 |
| 002 | 事件 topic 命名策略冲突 | ✅ 采用聚合 topic + action 字段策略4 聚合 topic | ai09 修文档 + coord 补 events.proto |
| 003 | Textbook/Chapter 事件遗漏 | ✅ 补登记 edu.content.textbook.events + chapter.events | ai09 已在 contract.md 补 + coord 同步 matrix.md |
| 004 | gRPC RPC 数量三方不一致 | ✅ 统一为 21 RPCTextbook 5 + Chapter 5 + KG 4 + Question 7 | ai09 修文档 + coord 修 matrix.md |
| 005 | core-edu → content 失效事件 topic 无定义 | ✅ 删除 02 文档 §5.2 该条目;联动改用 gRPC 调用 | ai09 |
| 006 | "直接 push main"与项目规则冲突 | ✅ 遵循总裁裁决trunk-based直接 push mainpost-commit review措辞优化为"trunk-based development" | ai09 |
| 007 | questions.created_by 迁移风险 | ✅ schema 用 `created_by varchar(32) NOT NULL DEFAULT 'system'`(历史数据回填 'system' | ai09 |
| 008 | 缓存策略与 API 版本化缺失 | ✅ P4 补缓存策略小节 + API 版本化说明 | ai09 |
| 009 | knowledge-points schema 缺字段 | ✅ P4 迁移补齐 difficulty + metadata + created_at + updated_at | ai09 |
| 010 | Sync Worker 链路 P4 不必要 | ✅ ES Sync Worker 标 P5Neo4j Sync Worker 输入仅 Outbox 事件P4 移除 safeCreateNode 同步写 | ai09 |
### 5.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ------------------------ | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| REST 端点风格 | query 参数(`GET /knowledge-points?chapterId=` | RESTful 规范 + 与 design doc 一致 |
| 事件 topic 策略 | 聚合 topic + action 字段4 topictextbook/chapter/knowledge_point/question | 与 matrix.md / events.proto ClassEvent 模式一致;减少 topic 数量 |
| RPC 总数 | 21TextbookService 5 + ChapterService 5 + KnowledgeGraphService 4 + QuestionService 7 | contract.md 为契约唯一源 |
| content 与 core-edu 关系 | content 是上游core-edu 调 content不消费 core-edu 事件 | ISSUE-005 建议 |
| Git 工作流 | trunk-based development直接 push main + post-commit review | 总裁裁决覆盖 project_rules §8 分支开发规则 |
| created_by 迁移 | `NOT NULL DEFAULT 'system'`(历史数据回填 + 新数据应用层校验) | ISSUE-007 方案二 |
| 缓存策略 | Redis 缓存教材树/章节树 + Outbox 事件触发失效 | 读多写少场景 |
| API 版本化 | REST `/v1/` 前缀 + gRPC proto package version | 破坏性变更隔离 |
| Neo4j 同步 | P4 改为 Outbox 事件驱动异步同步(移除 safeCreateNode 同步写) | 禁止业务事务内同步双写 |
### 5.4 ai09 执行项
1. 修改 content 02 文档:
- §4.1 REST 端点改 query 参数风格 + 补 DELETE prerequisite 端点
- §5.1 TOPIC_MAP 改为 4 聚合 topictextbook/chapter/knowledge_point/question events
- §5.2 删除 core-edu 失效事件条目
- §4.2 gRPC RPC 对齐 21 RPC补 Textbook Update/Delete + Chapter Update/Delete + Question Publish/Search
- §6 补"缓存策略"小节Redis + Outbox 失效)
- §4 补"API 版本化"说明REST `/v1/` 前缀)
- §1.1 图 ES Sync Worker 标 P5虚线/灰显Neo4j Sync Worker 输入仅 Outbox 事件
- 文档末尾措辞优化为"trunk-based development直接 push mainpost-commit review"
2. 修改源码 schemaquestions.created_by `NOT NULL DEFAULT 'system'`knowledge_points 补 difficulty/metadata/created_at/updated_at
3. P4 任务 T6重构 knowledge-points.service.ts 移除 safeCreateNode 同步写,改为发 Outbox 事件
### 5.5 coord 执行项
1. 补全 events.proto TextbookEvent/ChapterEvent/KnowledgePointEvent/QuestionEvent + schema_versionARB-006批次 0
2. 修正 matrix.md §2content 18 RPC → 21 RPC
3. 修正 matrix.md §4补登记 edu.content.textbook.events + chapter.events共 4 聚合 topic
---
## §6 ARB-006events.proto 补全(跨 iam/core-edu/content
### 6.1 背景
iam ISSUE-002、core-edu ISSUE-002、content ISSUE-002/003 共同指向 events.proto 不完整。当前 events.proto 仅定义 4 个 messageClassEvent/ExamEvent/HomeworkEvent/GradeEvent缺 iam 的 UserEvent/RoleEvent/AuditEvent、core-edu 的 AttendanceEvent、content 的 TextbookEvent/ChapterEvent/KnowledgePointEvent/QuestionEvent且所有 message 缺 schema_version 字段,文件头注释仍用旧 topic 命名。
### 6.2 仲裁结论
coord 在批次 0P2 启动前)补全 events.proto
| 新增 message | 字段 | 来源 |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| UserEvent | event_id/aggregate_id/event_type/occurred_at/user_id/email/name/roles/action(created/updated/deleted/role_changed)/schema_version/metadata | iam 02 §5.2 + president §5.5 |
| RoleEvent | event_id/aggregate_id/event_type/occurred_at/role_id/role_name/permissions/action(created/updated)/schema_version/metadata | iam 02 §5.2 |
| AuditEvent | event_id/aggregate_id/event_type/occurred_at/user_id/action(create/update/delete/login/logout/permission_change)/resource_type/resource_id/schema_version/metadata | president §5.5 |
| AttendanceEvent | event_id/aggregate_id/event_type/occurred_at/attendance_id/student_id/class_id/schedule_id/status/action(recorded)/schema_version/metadata | core-edu 02 §5.1 |
| TextbookEvent | event_id/aggregate_id/event_type/occurred_at/textbook_id/title/subject_id/grade_id/version/action(created/updated/published/archived)/schema_version/metadata | content contract.md §1.4 |
| ChapterEvent | event_id/aggregate_id/event_type/occurred_at/chapter_id/textbook_id/title/order/action(created/updated/deleted)/schema_version/metadata | content contract.md §1.4 |
| KnowledgePointEvent | event_id/aggregate_id/event_type/occurred_at/kp_id/chapter_id/title/difficulty/action(created/updated/prerequisite_added/prerequisite_removed)/prerequisite_id/schema_version/metadata | content contract.md §1.4 |
| QuestionEvent | event_id/aggregate_id/event_type/occurred_at/question_id/kp_id/type/difficulty/status/source/created_by/action(created/updated/published/deleted)/schema_version/metadata | content contract.md §1.4 |
**同时**
- 所有现有 messageClassEvent/ExamEvent/HomeworkEvent/GradeEvent`string schema_version = N;` 字段
- 文件头注释改为 `edu.teaching.*` 命名core-edu 事件)+ `edu.iam.*` 命名iam 事件)+ `edu.content.*` 命名content 事件)
### 6.3 Topic 命名策略(跨模块统一)
| 服务 | Topic 策略 | 示例 | 原因 |
| -------- | ------------------------ | ------------------------------------------------------------------------- | --------------------------------------- |
| iam | 聚合 topic + action 字段 | `edu.iam.user.events`(含 created/updated/deleted/role_changed | 事件量小,聚合减少 topic 数 |
| core-edu | 具体动作 topic | `edu.teaching.exam.created`(每事件独立 topic | 事件量大,独立 topic 利于分区与消费隔离 |
| content | 聚合 topic + action 字段 | `edu.content.knowledge_point.events`(含 created/updated/prerequisite_* | 事件量中等,聚合减少 topic 数 |
| msg | 具体动作 topic | `edu.notify.notification.created` | 通知事件量大,独立 topic |
> coord 裁决:允许跨服务采用不同 topic 粒度策略(聚合 vs 具体动作),以服务特征为准。所有 topic 命名统一遵循 `edu.<domain>.<aggregate>.<action>` 或 `edu.<domain>.<aggregate>.events` 格式。
---
## §7 ARB-007proto 契约补全汇总iam.proto + core_edu.proto
### 7.1 背景
iam ISSUE-005 和 core-edu ISSUE-001 共同指向 proto 契约未补全。coord 作为 shared-proto 维护者,在批次 0 统一补全。
### 7.2 iam.proto 补全12 RPC
| Service | RPC | 请求 | 响应 |
| ---------- | ----------------------- | ------------------------------ | ---------------------------- |
| IamService | Register | RegisterRequest | AuthResponse |
| IamService | Login | LoginRequest | AuthResponse |
| IamService | RefreshToken | RefreshTokenRequest | TokenPair |
| IamService | Logout | LogoutRequest | LogoutResponse |
| IamService | GetUserInfo | GetUserInfoRequest | UserInfo |
| IamService | BatchGetUsers | BatchGetUsersRequest | BatchGetUsersResponse |
| IamService | GetEffectivePermissions | GetEffectivePermissionsRequest | EffectivePermissionsResponse |
| IamService | GetEffectiveAccess | GetEffectiveAccessRequest | EffectiveAccessResponse |
| IamService | GetEffectiveDataScope | GetEffectiveDataScopeRequest | DataScopeResponse |
| IamService | GetViewports | GetViewportsRequest | ViewportsResponse |
| IamService | GetPublicKey | GetPublicKeyRequest | PublicKeyResponse |
| IamService | GetChildrenByParent | GetChildrenByParentRequest | ChildrenResponse |
> 对齐 iam_contract.md §1.1 的 12 RPC 清单。新增 8 RPCLogout/BatchGetUsers/GetEffectivePermissions/GetEffectiveAccess/GetEffectiveDataScope/GetViewports/GetPublicKey/GetChildrenByParent
### 7.3 core_edu.proto 补全5 Service 27 RPC
| Service | RPC | 状态 |
| ----------------- | -------------------------------------------------------------------------------------------------------------------- | --------------- |
| ClassService | GetClass / GetClassesByTeacher / BatchGetClasses / ListStudentsByClass | 新增 4 RPC |
| ExamService | CreateExam / GetExam / ListExamsByClass / UpdateExam / DeleteExam / **PublishExam** / **SubmitExam** / **GradeExam** | 已有 5 + 新增 3 |
| HomeworkService | AssignHomework / GetHomework / ListHomeworkByClass / SubmitHomework / **GradeHomework** | 已有 4 + 新增 1 |
| GradeService | RecordGrade / GetGrade / ListGradesByStudent / ListGradesByExam / ListGradesByHomework / **UpdateGrade** | 已有 5 + 新增 1 |
| AttendanceService | **RecordAttendance** / **GetAttendance** / **ListAttendanceByStudent** / **ListAttendanceByClass** | 新增 4 RPC |
**同时补全 message 字段**
- Exam补 subject_id / school_id / status_changed_at / status_changed_by / archived_at
- Homework补 subject_id / grace_period / school_id
- Grade补 total_score / school_id / idempotency_key
- SubmitHomeworkRequest补 answers 字段
> 对齐 core-edu_contract.md §1.1 的 27 RPC 清单。
### 7.4 coord 执行项
1. 补全 iam.proto 至 12 RPC含全部 message 定义)
2. 补全 core_edu.proto 至 5 Service 27 RPC含 ClassService + AttendanceService + P3 新增 5 RPC + message 字段补全)
3. 补全 events.protoARB-0067 个新 message + schema_version + 注释更新)
4. 运行 `buf lint` + `buf breaking` 确保零错误
5. 运行 `buf generate` 产出 TS gRPC 代码
6. 修正 coord-cross-review.md L312 状态
7. 更新 matrix.md §2 RPC 统计
---
## §10 ARB-008msg 模块 15 项 ISSUE 仲裁
### 10.1 背景
ai10 在 [msg_issue.md](./objections/msg_issue.md) 提请 15 项异议ISSUE-001~~005 已有仲裁核查 + ISSUE-006~~015 新发现),涉及 events.proto 字段缺失、proto 包名规则冲突、Kafka topic 三套约定、RPC 数量超预算、权限点不一致、降级方向矛盾、DLQ/幂等防线缺失、events.proto 缺 message、RPC 清单不一致、Kafka 发布事件不一致。
### 10.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| 001~005 | 已有仲裁核查 | ✅ 核查通过001/002/003004 待 coord 同步 events.proto 注释ARB-006 已覆盖005 待 coord 修正 004 §4.1 PushGW 方向 | coord |
| 006 | events.proto GradeEvent 缺 class_id + 全部事件缺 student_ids[] | ✅ coord 补全GradeEvent 补 class_idExam/Homework/GradeEvent 补 student_ids[]fan-out 广播用) | coord |
| 007 | proto 包名规则冲突project_rules §5 vs 实际) | ✅ 统一为 `next_edu_cloud.<domain>.v1`(与实际 proto 一致coord 更新 project_rules §5见 §13 ARB-011 | coord |
| 008 | Kafka topic 命名三套约定并存 | ✅ 统一裁决(见 §15 ARB-013msg 采用具体动作 topic`edu.notify.notification.sent` 等,与 core-edu 策略一致) | coord |
| 009 | RPC 数量超预算17 vs 13 | ✅ 采用方案 A维持 13 RPC 预算,裁剪 4 RPCBatchSendNotification/GetUnreadCount/BatchMarkAsRead/MarkAllAsRead 降级为 REST only | ai10 |
| 010 | markAsRead 权限点不一致 | ✅ 以 02 文档 §6.1 为准:`MSG_NOTIFICATION_READ`(非 MANAGE | ai10 |
| 011 | DB→ES 降级方向与 ai-allocation 相反 | ✅ 采用双向降级ES 故障→DB LIKEDB 故障→ES 只读(仅读操作可降级,写操作必须等 DB 恢复) | ai10 |
| 012 | 缺 DLQ 与三层幂等防线 | ✅ 非阻塞ai10 自行补充设计文档§3.1 补 msg_idempotency 表 + §5.5 三层幂等 + §5 DLQ 设计) | ai10 |
| 013 | events.proto 缺 4 类 message | ✅ coord 补全(见 §13 ARB-011MasteryEvent/NotificationEvent + UserEvent/RoleEvent 已在 ARB-006 覆盖) | coord |
| 014 | msg_contract.md 与 02 文档 RPC 清单不一致 | ✅ 待 ISSUE-009 仲裁后统一为 13 RPC两文档对齐 | ai10 |
| 015 | Kafka 发布事件不一致 | ✅ 待 ISSUE-008 仲裁后统一(见 §15 ARB-013 | ai10 + coord |
### 10.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ---------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------- |
| msg RPC 总数 | 13NotificationService 5 + PreferenceService 4 + TemplateService 4 | 维持 ai-allocation 预算;裁剪 4 RPC 降级 REST |
| Kafka topic 策略 | 具体动作 topic`edu.notify.notification.sent` / `.read` / `.recalled` / `.failed` | 与 core-edu 策略一致;事件量大,独立 topic 利于消费隔离 |
| markAsRead 权限 | `MSG_NOTIFICATION_READ` | 02 文档为准 |
| 降级策略 | 双向ES 故障→DB LIKEDB 故障→ES 只读) | ai-allocation §5 + 02 文档双向覆盖 |
| 三层幂等 | L1 Redis SETNX + L2 msg_idempotency 表 + L3 notifications.source_event_id 唯一索引 | known-issues 已记录 |
| DLQ | 重试 3 次后投递 `edu.notify.dlq` + 告警 | known-issues 已记录 |
| proto package | `next_edu_cloud.msg.v1`(保留现状) | 见 §13 ARB-011 |
### 10.4 ai10 执行项
1. 修改 msg 02 文档:
- §4.2 RPC 裁剪至 13移除 BatchSendNotification/GetUnreadCount/BatchMarkAsRead/MarkAllAsRead降级 REST only
- §5.2 Kafka topic 改为具体动作 topic`edu.notify.notification.sent` 等 4 个 per-event topic
- §3.1 补 msg_idempotency 表 schema
- §5.5 改为三层幂等防线
- §5 补 DLQ 设计(`edu.notify.dlq` + 重试 3 次 + 告警)
- §3.2.2/§3.4 补双向降级策略DB 故障→ES 只读)
- §6.1 markAsRead 权限改为 `MSG_NOTIFICATION_READ`
2. 修改源码 notifications.controller.ts markAsRead 权限点
3. msg_contract.md §1.1 RPC 清单对齐 13 RPC + §1.4 topic 对齐具体动作 topic
### 10.5 coord 执行项
1. 补全 events.protoARB-011NotificationEvent + MasteryEvent + GradeEvent 补 class_id + 全部事件补 student_ids[]
2. 修正 004 §4.1 PushGW 方向表述为"Msg → push-gateway (gRPC)"
3. 修正 matrix.md §4msg topic 改为 `edu.notify.notification.*` 具体动作 topic
---
## §11 ARB-009data-ana 模块 6 项 ISSUE 仲裁
### 11.1 背景
ai11 在 [data-ana_issue.md](./objections/data-ana_issue.md) 提请 6 项异议,涉及 iam.proto 缺 GetEffectiveDataScope、events.proto 缺 AIUsageEvent、analytics.proto 未补全至 12 RPC、004 章节引用断裂、MasteryEvent topic 不一致、coord-cross-review §8.2 声明与实际不符。
### 11.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------- |
| 001 | iam.proto 缺 GetEffectiveDataScope RPC | ✅ coord 批次 0 补全 iam.proto 12 RPCARB-007 已覆盖,含 GetEffectiveDataScope | coord |
| 002 | events.proto 缺 AIUsageEvent message | ✅ coord 补全(见 §13 ARB-011 | coord |
| 003 | analytics.proto 仅 3 RPC声称 12 RPC 未落实 | ✅ coord 批次 0 补全 analytics.proto 至 12 RPC见 §14 ARB-012 | coord |
| 004 | 004 章节引用断裂coord 整改 #7/#8/#9/#10 未落实) | ✅ coord 补全 004 §7.2/§1.2/§4.1/§12.2 对应章节 | coord |
| 005 | MasteryEvent topic 命名三处不一致 | ✅ 统一为 `edu.insight.mastery.updated` + `edu.insight.warning.triggered`domain=insight 智能洞察领域) | coord 修 matrix.md + ai11 已对齐 |
| 006 | coord-cross-review §8.2 声明与实际不符 | ✅ coord 更正 §8.2 状态为"待执行",明确补全时间点 | coord |
### 11.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ------------------ | --------------------------------------------------------------- | --------------------------------------------------------------------- |
| analytics.proto | 12 RPC4 端 Dashboard + Warning + Mastery + Server Streaming | 02 文档 §4.2 已设计coord 补全 proto |
| MasteryEvent topic | `edu.insight.mastery.updated` | 004 §7.2 命名规范 `edu.<domain>.<aggregate>.<action>`domain=insight |
| WarningEvent topic | `edu.insight.warning.triggered` | 同上 |
| 004 章节补全 | coord 补全 §7.2/§1.2/§4.1/§12.2 对应段落 | coord-cross-review §6 整改 #7/#8/#9/#10 |
| §8.2 声明更正 | "✅ 已完成" → "⏳ 待 coord 补全ARB-007/012" | 实际 proto 未补全 |
| Python Outbox 豁免 | ✅ 确认MasteryUpdated/WarningTriggered 派生数据豁免) | coord-cross-review §3.3 |
### 11.4 ai11 执行项
1. data-ana 01/02 文档:将 004 §4.2/§11.4/§11.5/§15.3 引用从 coord-cross-review.md 回切到 004 对应章节(待 coord 补全后)
2. contract.md §1.4 topic 已对齐 `edu.insight.*`(核查通过)
### 11.5 coord 执行项
1. 补全 analytics.proto 至 12 RPCARB-012批次 0
2. 补全 events.proto AIUsageEvent + MasteryEventARB-011批次 0
3. 补全 iam.proto GetEffectiveDataScopeARB-007 已覆盖)
4. 补全 004 §7.2(补登 6 个 topic + CDC 命名规范)/§1.2(端口列)/§4.1gRPC 启用阶段矩阵)/§12.2(派生数据事件 Outbox 豁免条款)
5. 更正 coord-cross-review.md §8.2 状态
6. 修正 matrix.md §4data-ana topic 改为 `edu.insight.*`
---
## §12 ARB-010ai 模块 9 项 ISSUE 仲裁
### 12.1 背景
ai12 在 [ai_issue.md](./objections/ai_issue.md) 提请 9 项异议,涉及 matrix.md 端口不同步、ai 用量事件 topic 三义、ai.proto 待补全、events.proto 缺 AIUsageEvent、contract 与设计文档矛盾、Temporal 决策点、iam GetEffectiveDataScope、proto package 命名、ActionState 整改。
### 12.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ |
| 01 | matrix.md 端口 50057 vs 50058 不同步 | ✅ 统一为 50058port-allocation.md §7 为准coord 修 matrix.md | coord |
| 02 | ai 用量事件 topic 三义未决 | ✅ 统一为 `edu.ai.usage`(见 §15 ARB-013 | coord |
| 03 | ai.proto 待补全 | ✅ P5 目标 6 RPCChat/StreamChat/GenerateQuestion/StreamGenerateQuestion/OptimizeExpression/GenerateLessonPlan备课状态查询/确认用 HTTP 端点(见 §14 ARB-012 | coord 补 proto |
| 04 | events.proto 缺 AIUsageEvent | ✅ coord 补全(见 §13 ARB-011 | coord |
| 05 | contract 与设计文档矛盾 | ✅ ai12 自纠重写 contract端口 50058 / 补 HTTP 端点 / topic 待 §15 裁决后填 / 错误码对齐 02 §6.2 / 删除消费事件) | ai12 |
| 06 | 备课工作流 TemporalP6 决策点) | ✅ P5 用 BackgroundTasks + RedisP6 由 coord 评估 Temporal 引入roadmap 标注 P6 决策点) | ai12 P5 + coord P6 |
| 07 | iam GetEffectiveDataScope 待 P4 补全 | ✅ coord 批次 0 补全 iam.proto 12 RPCARB-007 已覆盖) | coord |
| 08 | proto package 命名不符合 project_rules §5 | ✅ 统一为 `next_edu_cloud.<domain>.v1`(见 §13 ARB-011 | coord |
| 09 | 响应信封偏离 ActionState | ✅ P5 实施时整改:所有返回值改为 ActionStatedegraded 移至 `error.details.degraded` | ai12 |
### 12.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ------------- | --------------------------------------------- | ----------------------------------------- |
| ai gRPC 端口 | 50058 | port-allocation.md §7 为准 |
| ai RPC 总数 | 6P5 目标) | 避免 RPC 膨胀;备课状态查询/确认用 HTTP |
| ai 用量 topic | `edu.ai.usage` | 最简短,符合 `edu.<domain>.<action>` 约定 |
| proto package | `next_edu_cloud.ai.v1`(保留现状) | 见 §13 ARB-011 |
| Temporal | P5 不引入BackgroundTasks + RedisP6 评估 | 避免过早引入复杂度 |
| ActionState | P5 强制整改degraded 移至 error.details | 004 §11.5 |
### 12.4 ai12 执行项
1. 重写 ai_contract.md 对齐设计文档(端口 50058 / 补 HTTP 端点 / topic `edu.ai.usage` / 错误码对齐 02 §6.2 / 删除消费事件或标注 P6+
2. P5 实施时整改 ActionStatemain.py 返回值改为 `{success, data, error:{code,message,details,traceId}}`degraded 移至 `error.details.degraded`
3. P5 备课工作流用 BackgroundTasks + Redis02 文档 §2.4 状态机已设计)
4. 修正 01/02 文档引用004 §7.2/§1.2 引用失实,改引 port-allocation.md + coord 仲裁
### 12.5 coord 执行项
1. 补全 ai.proto 至 6 RPCARB-012批次 0
2. 补全 events.proto AIUsageEventARB-011批次 0
3. 修正 matrix.md §2/§8ai gRPC 端口 50057 → 50058
4. 在 roadmap 标注 P6 决策点Temporal 引入评估)
5. 在 known-issues §2.9 ai 分区记录 ActionState 整改约束
---
## §13 ARB-011events.proto 扩展补全 + proto package 命名统一
### 13.1 背景
msg ISSUE-013、data-ana ISSUE-002、ai ISSUE-04 共同指向 events.proto 还缺 msg/data-ana/ai 相关 messageARB-006 已覆盖 iam/core-edu/content 的 7 个 message。msg ISSUE-007 + ai ISSUE-08 共同指向 proto package 命名规则冲突。
### 13.2 events.proto 扩展补全(在 ARB-006 基础上)
| 新增 message | 字段 | 来源 |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| MasteryEvent | event_id/aggregate_id/event_type/occurred_at/student_id/subject_id/mastery_score/action(updated)/schema_version/metadata | data-ana 02 文档 |
| WarningEvent | event_id/aggregate_id/event_type/occurred_at/student_id/warning_type/severity/action(triggered)/schema_version/metadata | data-ana 02 文档 |
| NotificationEvent | event_id/aggregate_id/event_type/occurred_at/notification_id/user_id/channel/action(sent/read/recalled/failed)/schema_version/metadata | msg 02 文档 |
| AIUsageEvent | event_id/request_id/user_id/school_id/provider/model/operation/prompt_tokens/completion_tokens/total_tokens/latency_ms/success/degraded/action(usage)/schema_version/metadata | ai 02 文档 §3.3 |
**同时**
- GradeEvent 补 `class_id` 字段
- ExamEvent/HomeworkEvent/GradeEvent 补 `student_ids[]` 字段复数fan-out 广播用)
> events.proto 最终包含 15 个 messageClassEvent/ExamEvent/HomeworkEvent/GradeEvent原有 4 + 补字段)+ UserEvent/RoleEvent/AuditEvent/AttendanceEvent/TextbookEvent/ChapterEvent/KnowledgePointEvent/QuestionEventARB-006 新增 8+ MasteryEvent/WarningEvent/NotificationEvent/AIUsageEvent本节新增 4= 4+8+4 = 16 个 message含原有 4
### 13.3 proto package 命名统一
| 裁决点 | 结论 | 依据 |
| --------------------- | ------------------------------------------------ | --------------------------------------- |
| proto package 命名 | `next_edu_cloud.<domain>.v1`(保留现状) | 所有 proto 文件已采用此格式,改动成本高 |
| project_rules §5 更新 | `edu.<domain>.v1``next_edu_cloud.<domain>.v1` | 与实际 proto 一致 |
### 13.4 coord 执行项
1. 补全 events.proto 4 个新 messageMasteryEvent/WarningEvent/NotificationEvent/AIUsageEvent
2. 补全 GradeEvent class_id + 全部事件 student_ids[] 字段
3. 更新 project_rules §5 包名规范为 `next_edu_cloud.<domain>.v1`需人类审批project_rules §15.7 敏感文件)
4. 运行 `buf lint` + `buf breaking` 确保零错误
---
## §14 ARB-012analytics.proto + ai.proto 补全
### 14.1 背景
data-ana ISSUE-003 和 ai ISSUE-03 共同指向 proto 契约未补全。coord 作为 shared-proto 维护者,在批次 0 统一补全。
### 14.2 analytics.proto 补全12 RPC
| Service | RPC | 说明 |
| ---------------- | ---------------------- | ----------------------------- |
| AnalyticsService | GetClassPerformance | 班级表现 |
| AnalyticsService | GetStudentWeakness | 学生薄弱点 |
| AnalyticsService | GetLearningTrend | 学习趋势 |
| AnalyticsService | StreamClassPerformance | Server Streaming 班级实时表现 |
| AnalyticsService | GetStudentDashboard | 学生仪表盘 |
| AnalyticsService | GetTeacherDashboard | 教师仪表盘 |
| AnalyticsService | GetAdminDashboard | 管理员仪表盘 |
| AnalyticsService | GetParentDashboard | 家长仪表盘 |
| AnalyticsService | TriggerWarning | 触发预警 |
| AnalyticsService | GetWarnings | 查询预警列表 |
| AnalyticsService | UpdateMastery | 更新掌握度 |
| AnalyticsService | GetMasteryByStudent | 查询学生掌握度 |
> 对齐 data-ana 02 文档 §4.2 的 12 RPC 清单(含 1 Server Streaming
### 14.3 ai.proto 补全6 RPC
| Service | RPC | 说明 |
| --------- | ---------------------- | ------------ |
| AiService | Chat | 单轮对话 |
| AiService | StreamChat | 流式对话 |
| AiService | GenerateQuestion | 生成题目 |
| AiService | StreamGenerateQuestion | 流式生成题目 |
| AiService | OptimizeExpression | 优化表达 |
| AiService | GenerateLessonPlan | 生成教案 |
**同时扩展 message 字段**
- GenerateQuestionRequest补 grade / knowledge_point_ids / question_type / count
- ChatRequest补 user_id / session_id / data_scope可选
**备课工作流状态查询/确认用 HTTP 端点**(非 gRPC
- `GET /ai/v1/lesson/preparation/{id}`:查询备课状态
- `POST /ai/v1/lesson/preparation/{id}/confirm`:确认入库
### 14.4 coord 执行项
1. 补全 analytics.proto 至 12 RPC含 Server Streaming
2. 补全 ai.proto 至 6 RPC + message 字段扩展
3. 运行 `buf lint` + `buf breaking` 确保零错误
4. 运行 `buf generate` 产出 TS/Go/Python gRPC 代码
---
## §15 ARB-013Kafka topic 命名统一裁决(跨全模块)
### 15.1 背景
msg ISSUE-008/015、data-ana ISSUE-005、ai ISSUE-02 共同指向 Kafka topic 命名跨模块不一致。需 coord 统一裁定。
### 15.2 仲裁结论
**统一命名规则**`edu.<domain>.<aggregate>.<action>``edu.<domain>.<aggregate>.events`
**Topic 粒度策略**按服务特征区分coord 裁决允许差异):
| 服务 | Topic 策略 | Topic 清单 | 原因 |
| -------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| iam | 聚合 topic + action 字段 | `edu.iam.user.events` / `edu.iam.role.events` / `edu.iam.audit.created` | 事件量小,聚合减少 topic 数 |
| core-edu | 具体动作 topic | `edu.teaching.exam.created` / `.updated` / `.deleted` / `.published` / `.submitted` / `edu.teaching.homework.assigned` / `.submitted` / `.graded` / `edu.teaching.grade.recorded` / `.updated` / `edu.teaching.attendance.recorded` / `edu.teaching.class.transferred` | 事件量大,独立 topic 利于分区 |
| content | 聚合 topic + action 字段 | `edu.content.textbook.events` / `edu.content.chapter.events` / `edu.content.knowledge_point.events` / `edu.content.question.events` | 事件量中等,聚合减少 topic 数 |
| msg | 具体动作 topic | `edu.notify.notification.sent` / `.read` / `.recalled` / `.failed` | 通知事件量大,独立 topic |
| data-ana | 具体动作 topic | `edu.insight.mastery.updated` / `edu.insight.warning.triggered` | 派生数据事件Outbox 豁免) |
| ai | 具体动作 topic | `edu.ai.usage` | 派生数据事件Outbox 豁免) |
### 15.3 域名映射
| 服务 | domain | 依据 |
| -------- | ---------- | --------------------------------- |
| iam | `iam` | 服务名 |
| core-edu | `teaching` | 教学领域(非服务名 core_edu |
| content | `content` | 内容领域 |
| msg | `notify` | 通知领域(非服务名 msg |
| data-ana | `insight` | 智能洞察领域(非服务名 data_ana |
| ai | `ai` | AI 领域 |
### 15.4 matrix.md §4 同步更新
coord 修正 matrix.md §4 Kafka 事件矩阵,全部 topic 对齐上述清单。
### 15.5 各 AI 执行项
各 AI 检查自身 02 文档 TOPIC_MAP + contract.md §1.4,对齐本仲裁的 topic 命名。具体差异见各模块 ARB 章节。
---
## §16 ARB-014api-gateway 模块 4 项内联 ISSUE 仲裁
### 16.1 背景
ai01 的 [api-gateway_issue.md](./objections/api-gateway_issue.md) 文件仅含标题未填写实质内容(文件截断,仅 2 行),但其 [api-gateway_contract.md](./contracts/api-gateway_contract.md) v2 内联了 4 项待仲裁 ISSUE§1.2.2 注 3 + §2.4 + §3.1。coord 提取 contract.md 中的内联 ISSUE 逐条仲裁。
### 16.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------- |
| 001 | JWKS 拉取方式gRPC vs HTTP | ✅ 已确认 HTTP JWKScontract v2 §2.3 已执行:`GET /.well-known/jwks.json`TTL 5min 缓存) | ai01已完成 |
| 002 | shared-go 包接入 | ✅ shared-go 包骨架已完成contract §3.1 显示 ✅ai01 直接 import `packages/shared-go` 的 jwks/logger/tracer/env 4 模块 | ai01已就绪 |
| 003 | API 版本化路由方案(双 /v1 前缀) | ✅ 采纳方案 A前端调用 `/api/v1/<service>/v1/*`(双 /v1 前缀Gateway 纯透传无路径重写) | ai01 |
| 004 | zap vs slog 日志库选型 | ✅ 遵循 project_rules §12 使用 **zap**project_rules 明确规定 Go 日志用 zap | ai01 |
### 16.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ----------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| JWKS 拉取 | HTTP `GET /.well-known/jwks.json`(非 gRPC | president §2.16 + contract v2 §2.3 |
| Gateway gRPC 消费 | **无**Gateway 不消费任何 gRPC纯 HTTP 透传) | president §2.16 + B3 裁决(权限由下游 Controller 自校验) |
| API 版本化 | 方案 A`/api/v1/<service>/v1/*` 双前缀Gateway 不做路径重写 | 纯透传最简,避免路径重写 bug`/api/v1` 是 Gateway API 前缀,`/<service>/v1` 是服务内部 API 前缀 |
| Go 日志库 | zap对齐 project_rules §12 | project_rules 强制规定Go 1.22 slog 为备选,需 project_rules 变更后评估 |
| matrix.md §2 修正 | 移除 api-gateway 为 iam gRPC 消费方contract §2.1 勘误已指出) | Gateway 不消费 gRPC |
### 16.4 ISSUE-003 方案 A 路径规范
| 层级 | 路径格式 | 示例 |
| ------------ | ----------------------------------------------------- | -------------------------------------- |
| 前端调用 | `/api/v1/<service>/v1/<resource>` | `/api/v1/iam/v1/register` |
| Gateway 透传 | 原样转发到 `<service>:<port>/<service>/v1/<resource>` | iam:3002`/iam/v1/register` |
| 服务内部路由 | `/<service>/v1/<resource>` | iam Controller 注册 `/iam/v1/register` |
> **双 /v1 语义**:外层 `/api/v1` 是 Gateway 层 API 版本(全局),内层 `/v1` 是服务内部 API 版本(独立演进)。此设计允许 Gateway 和服务各自独立版本化。
### 16.5 ai01 执行项
1. P2.7 任务统一迁移路由至 `/api/v1/<service>/v1/*` 双前缀格式(当前 P1 代码为 `/api/v1/<service>/*` 单前缀)
2. 使用 zap 日志库import `packages/shared-go/logger`
3. ISSUE-001/002 已落地,无需额外动作
4. 补充 issue.md 文件内容(当前为空,后续如有新问题需按格式追加)
### 16.6 coord 执行项
1. 修正 matrix.md §2 gRPC 接口提供方矩阵:移除 api-gateway 为 iam gRPC 消费方
2. 确认 shared-go 4 模块骨架已就绪contract §3.1 已标 ✅)
---
## §17 ARB-015push-gateway 模块 7 项 ISSUE 仲裁
### 17.1 背景
ai02 在 [push-gateway_issue.md](./objections/push-gateway_issue.md) 提请 7 项异议,涉及 SSE 端点冲突、内部 API 鉴权命名、容量目标、端点路径、审计表设计、Redis /readyz 冲突、02 文档缺 ADR/NFR。coord 对照 [push-gateway_contract.md](./contracts/push-gateway_contract.md) v2 逐条仲裁。
### 17.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
| 001 | SSE 端点三方冲突 | ✅ 采纳 ai02 建议:**不支持 SSE仅 WebSocket**。移除 contract.md §1.2 的 `/sse` 端点 + matrix.md §5 SSE 行 | coord 修 contract + matrix + ai02 确认 |
| 002 | 内部 API 鉴权命名不一致 | ✅ 统一为 `X-Internal-Token` 头 + `INTERNAL_API_TOKEN` 环境变量(对齐总裁 §7.2 | ai02 改代码 + coord 修 contract |
| 003 | 容量目标 50k vs 10w+ | ✅ 统一为 **10w+**(对齐 02 文档 + pending-features 权威) | coord 修 modules/README §7 |
| 004 | /internal/send vs /internal/push | ✅ 统一为 `/internal/push`ai02 已自行修复contract v2 已对齐) | ai02已完成 |
| 005 | 审计表设计缺失 | ✅ 方案 2审计由 msg 服务维护msg 已落库push-gateway 保持无 DB 定位 | ai10 确认审计字段 + ai02 无需引入 DB |
| 006 | ISSUE-058 与 055 Redis /readyz 冲突 | ✅ **Redis 软失败**(仅告警 + `degraded: true` + 返 200不返 503从 ISSUE-055 必需依赖列表中移除 push-gateway → Redis | coord 澄清两裁决优先级 |
| 007 | 02 文档缺 ADR/NFR/容量/失败模式 | ✅ P5批次 4补全 02 文档 §14-§17 四章节ADR/非功能性需求/失败模式/容量估算) | ai02 |
### 17.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ------------- | ----------------------------------------------------- | ---------------------------------------------------------------------- |
| SSE 端点 | **不支持**,仅 WebSocket | 单一协议降低维护成本SSE 单向下行不适合双向协议 |
| 内部鉴权 | `X-Internal-Token` + `INTERNAL_API_TOKEN`(共享密钥) | 总裁 §7.2mTLS P5 成本过高K8s NetworkPolicy 已隔离 |
| 容量目标 | 10w+ 连接/单实例 | pending-features 权威Go goroutine-per-connection 约 2-3GB/10w 连接 |
| 审计表归属 | msg 服务维护push-gateway 无 DB | 保持 push-gateway 无 DB 定位,避免引入持久化层 |
| Redis /readyz | **软失败**(仅告警不阻塞,返 200 + degraded | push-gateway 重启不解决 Redis 故障Redis 故障时单实例仍能服务本地连接 |
| Kafka /readyz | 软失败(仅告警 + degraded | ISSUE-055 裁决 |
| 心跳协议 | RFC 6455 控制帧Ping/Pong30s 间隔) | 02 文档 §10 |
### 17.4 ISSUE-006 Redis 软失败裁决详情
**冲突**
- ISSUE-055president §3.3Redis 列为"必需依赖",失败返 503
- ISSUE-058president §4.3Redis /readyz "仅告警不阻塞,避免雪崩"
**coord 裁决**:以 ISSUE-058 为准后裁决优先Redis 对 push-gateway 为**软失败**。
**理由**
1. push-gateway 重启不解决 Redis 故障Redis 是跨实例广播依赖,非本地状态)
2. Redis 故障时单实例仍能服务本地连接(仅跨实例广播失效)
3. 重启会丢失本地连接表,加剧雪崩风险
4. ISSUE-055 的"必需依赖"列表应排除 push-gateway → RedisRedis 故障不触发 Pod 重启)
**修正**004 §7.2 / coord-cross-review 中 ISSUE-055 必需依赖列表push-gateway → Redis 标注为"软失败ISSUE-058 裁决覆盖)"。
### 17.5 ai02 执行项
1. 修改源码鉴权头:`X-Internal-Key``X-Internal-Token``INTERNAL_API_KEY``INTERNAL_API_TOKEN`ISSUE-002
2. 02 文档 §3.1 补 Hub 启动重建机制SADD + EXPIRE 60s + 清空旧 instanceID 成员ISSUE-058 回写)
3. 02 文档 §6.7 /readyz Redis 检查改为软失败(返 200 + degraded不返 503ISSUE-006
4. 02 文档 §5.4 添加"设计决策记录gRPC vs HTTP 协议选型"章节,标注"coord 已采纳 P1"ISSUE-056 回写)
5. 02 文档 §5.1 topic 已对齐 `edu.notification.requested`ISSUE-053 回写确认)
6. 02 文档补 §14-§17 四章节ADR/NFR/失败模式/容量估算P5 批次 4 补全ISSUE-007
7. 02 文档补 `push_gateway_redis_set_rebuild_total` 指标 + 60s 不一致窗口文档说明ISSUE-058 回写)
8. ISSUE-001/003/004/005 由 coord 修文档ai02 确认
### 17.6 coord 执行项
1. 修正 contract.md §1.2:移除 `/sse` 端点ISSUE-001
2. 修正 matrix.md §5移除 push-gateway SSE 行ISSUE-001
3. 修正 modules/push-gateway/README.md §750k → 10w+ISSUE-003
4. 修正 contract.md §1.2:鉴权头统一为 `X-Internal-Token`ISSUE-002contract v2 已部分对齐,确认最终)
5. 修正 004 §7.2 / coord-cross-reviewISSUE-055 必需依赖列表中 push-gateway → Redis 标注"软失败"
6. ISSUE-005 协调 ai10 确认 msg 审计表覆盖 push-gateway 推送结果字段
---
## §18 ARB-016teacher-bff 模块 3 项 ISSUE 仲裁
### 18.1 背景
ai03 在 [teacher-bff_issue.md](./objections/teacher-bff_issue.md) 提请 3 项异议,涉及 admin 命名空间 P2 预留与 ARB-001 冲突、dashboard classes 数据来源与调用链冲突、GraphQL schema 文件命名不一致。coord 对照 [teacher-bff_contract.md](./contracts/teacher-bff_contract.md) v2 逐条仲裁。
### 18.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| 001 | admin 命名空间 P2 预留与 ARB-001 "P2 不包含" 冲突 | ✅ 以总裁裁决为准president > coord修正 ARB-001 §1.3 为 "P2 预留 admin schema 命名空间占位" | coord 修 ARB-001 |
| 002 | P2 dashboard classes 数据来源与调用链冲突 | ✅ 采纳 president §3.5P2 classes 数据从 iam gRPC 获取GetViewports/GetEffectiveAccess不调 classes 服务 | coord 修 ARB-001 + ai03 修文档 |
| 003 | GraphQL schema 文件命名不一致 | ✅ 以总裁 §2.17 为准:统一为 `teacher-bff.schema.graphql` | coord 修 ARB-001 + ai03 创建文件 |
### 18.3 关键裁决
| 裁决点 | 结论 | 依据 |
| -------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
| admin 命名空间 P2 | **P2 预留** schema 占位(声明 `admin` Query/Mutation 类型骨架Resolver 返 nullP6 实现 | president §5.1 + §7.3(裁决优先级 president > coord |
| P2 classes 数据来源 | **iam gRPC**GetViewports/GetEffectiveAccess 返回关联班级),不调 classes 服务 | president §3.5 + B2 裁决classes P2 无 gRPC禁止 REST 过渡) |
| P3+ classes 数据来源 | 切换为 `core-edu.ClassService.GetClassesByTeacher` RPCcore-edu gRPC 50053 就绪后) | ARB-007 已补全 ClassService 4 RPC |
| schema 文件名 | `teacher-bff.schema.graphql`(统一 `<bff-name>.schema.graphql` 格式) | president §2.17 |
| 裁决优先级 | president > coordARB-001 修正为对齐总裁裁决) | 总裁裁决覆盖 coord 仲裁 |
### 18.4 ISSUE-002 P2 dashboard 调用链修正
**原 ARB-001 §1.4 第 4 条**
> dashboard Resolver 并行调用 iam3 RPC+ classes1 RPC用 DataLoader 防御 N+1
**修正为**
> dashboard Resolver 并行调用 iam gRPCGetUserInfo + GetViewports + GetEffectiveAccessclasses 列表从 iam 返回数据推导P3 core-edu gRPC 就绪后切换为 `GetClassesByTeacher` RPC
**理由**
1. classes P2 无 gRPC serverclasses.proto 注释 "P3 起转 gRPC"
2. B2 裁决禁止 REST 过渡
3. president §3.5 裁决 P2 班级列表数据来自 iam
### 18.5 ai03 执行项
1. 创建 `packages/shared-ts/contracts/graphql/teacher-bff.schema.graphql`(文件名用 `.schema.graphql`ISSUE-003
2. schema 中预留 `admin` 命名空间占位(`admin.*` Query/Mutation 类型骨架Resolver 返 nullISSUE-001
3. dashboard Resolver P2 实现:调 iam gRPC 获取 classes 数据(不调 classes 服务ISSUE-002
4. P3+ 切换 dashboard classes 数据源为 `core-edu.ClassService.GetClassesByTeacher`
### 18.6 coord 执行项
1. 修正 ARB-001 §1.3admin 命名空间改为 "P2 预留 schema 占位"
2. 修正 ARB-001 §1.3/§1.4:文件名改为 `teacher-bff.schema.graphql`
3. 修正 ARB-001 §1.4 第 4 条dashboard classes 数据来源改为 iam gRPC不调 classes 服务)
4. 修正 ARB-001 §1.2 GraphQL schema 代码块DataScope 枚举去掉 DISTRICT 改 SUBJECTARB-003 ISSUE-004 已裁决,需同步 ARB-001
---
## §19 ARB-017student-bff 模块 4 项新 ISSUE 仲裁
### 19.1 背景
ai04 在 [student-bff_issue.md](./objections/student-bff_issue.md) §1 提请 4 项新异议STU-001~004涉及 01 文档与 B1/B2/B5 裁决冲突、02 引用不存在的 004 章节、02 §8.3 八项已裁决决策未更新、GraphQL schema 第一版未起草。coord 对照 [student-bff_contract.md](./contracts/student-bff_contract.md) v2 逐条仲裁。
### 19.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------ |
| STU-001 | 01 文档与 B1/B2/B5 裁决冲突 | ✅ 与 ISSUE-028 合并处理01 文档随 02 文档一并回写(删除 REST 端点清单、改 GraphQL、错误码改 BFF_STUDENT_ | ai04 |
| STU-002 | 02 引用不存在的 004 §11.4/§11.5 | ✅ coord 补全 004 §11.4(错误码前缀矩阵)+ §11.5ActionState 信封规范)章节 | coord |
| STU-003 | 02 §8.3 八项已裁决决策未更新 | ✅ 02 文档回写时删除已裁决项的"待仲裁"标注,改为"已裁决(见 coord-final-decisions §2 BX" | ai04 |
| STU-004 | GraphQL schema 第一版未起草 | ✅ ai04 在批次 1 等待期产出 schema 草案,存放 `packages/shared-ts/contracts/graphql/student-bff.schema.graphql` | ai04 |
### 19.3 关键裁决
| 裁决点 | 结论 | 依据 |
| -------------------- | ---------------------------------------------------------- | ------------------------------------------ |
| 01 文档回写范围 | 01 + 02 一并回写01 不作为历史快照保留,必须对齐裁决) | ISSUE-028 + STU-001 合并 |
| 004 §11.4/§11.5 补全 | coord 补全错误码前缀矩阵 + ActionState 信封规范章节 | 004 作为架构设计意图唯一源,不应有断裂引用 |
| schema 仲裁时机 | ai04 批次 1 等待期起草 → coord 批次 2 启动前仲裁第一版 | president §2.2 |
| schema 文件名 | `student-bff.schema.graphql`(统一格式,对齐 teacher-bff | president §2.17 |
| 02 §8.3 已裁决项 | B1/B2/B3/B4/B5/B6/B7/B8 全部已裁决,删除"待仲裁"标注 | coord-final-decisions §2 |
### 19.4 ISSUE-028 回写范围确认
ai04 须在批次 2 启动前完成 02 文档回写president §3.4 裁决),回写范围:
1. **§4 API 设计**21 个 REST 端点 → GraphQL Query/Mutation 清单
2. **§9.2 演进路线**:删除"REST→GraphQL 演进"(违反"不分阶段"原则)
3. **§9.3 通信协议演进**:删除"HTTP→gRPC 演进"(违反 B2
4. **§3.1 下游通信**"HTTP fetch当前阶段" → "gRPC 调用下游(@grpc/grpc-js + @bufbuild/protobuf"
5. **§3.3/§6 错误码**`STUDENT_BFF_``BFF_STUDENT_`
6. **§8.3 未决决策**8 项已裁决项标注"已裁决",仅保留 #7/#10/#11/#12 合理设计决策
7. **01 文档**:同步回写(删除 REST 假设、对齐错误码前缀、删除已裁决项重复提请)
### 19.5 ai04 执行项
1. 批次 1 等待期产出 `student-bff.schema.graphql` 草案ISSUE-STU-004
2. 批次 2 启动前回写 01 + 02 文档ISSUE-028 + STU-001/003范围见 §19.4
3. 02 文档引用源修正004 §11.4/§11.5 → coord 补全后引用(或暂引 coord-final-decisions G14/G8
4. 实现 DownstreamClient 回写 teacher-bffB8 裁决)
### 19.6 coord 执行项
1. 补全 004 §11.4错误码前缀矩阵GW_/IAM_/CORE_EDU_/BFF_TEACHER_/BFF_STUDENT_/BFF_PARENT_/MSG_/PUSH_/DATA_ANA_/AI_+ §11.5ActionState 信封规范:`{success, data, error:{code,message,details,traceId}}` + degraded 放 error.details
2. 批次 2 启动前仲裁 student-bff schema 第一版president §2.2
---
## §20 ARB-018parent-bff 模块 10 项 ISSUE 仲裁
### 20.1 背景
ai05 在 [parent-bff_issue.md](./objections/parent-bff_issue.md) 提请 10 项异议,涉及 01 文档未同步、ChildGuard TTL 不一致、契约引用错误、004 依赖图未同步、parent-portal REST vs GraphQL 跨模块冲突、proto 包名缺失、Notification.childId 缺失、ClassService 缺失、责任方过时、02 缺 ADR/NFR。coord 对照 [parent-bff_contract.md](./contracts/parent-bff_contract.md) 逐条仲裁。
### 20.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
| 001 | 01 文档未同步 ai05 接手 + U3/U4/C1 仲裁 | ✅ 01 作为阶段 1 历史快照保留原样,以 02 为准02 已执行 U3/U4/C1 | ai05 标注 01 为历史快照 |
| 002 | 02 文档 ChildGuard TTL 三处不一致60s/30s | ✅ 统一为 **30s**§3.1.1 表格改为 30s对齐 §9 #2 + §13 #7 | ai05 修文档勘误 |
| 003 | contract.md 引用 I3 → 应为 I6 | ✅ 修正为 I6 裁决coord-final-decisions §1 I6家长-学生关联) | ai05 修 contract 引用 |
| 004 | 004 §4 + matrix.md §1 未同步 C6 仲裁(缺 DataAna + Msg | ✅ coord 补全 004 §4 服务依赖图 + matrix.md §1 依赖矩阵(加 PBFF → DataAna + PBFF → Msg | coord |
| 005 | parent-portal 01 文档按 REST 消费 parent-bff跨模块冲突 | ✅ coord 协调 ai15 将 parent-portal 01/02 改为 GraphQL 消费(`POST /api/v1/parent/v1/graphql` | coord 协调 ai15 |
| 006 | proto 包名引用缺 next_edu_cloud 前缀 | ✅ 统一补 `next_edu_cloud.` 前缀ARB-011 已裁决ai05 修 02 §3.3 DTO 映射表) | ai05 |
| 007 | GraphQL Notification.childId 在 msg.proto 缺失 | ✅ coord 协调 ai10 在 msg.proto Notification message 补 `string child_id = 9;`(可选,非家长通知为空) | coord 协调 ai10 |
| 008 | core_edu.proto 缺 ClassService | ✅ coord 已在 ARB-007 补全 ClassService 4 RPCGetClass/GetClassesByTeacher/BatchGetClasses/ListStudentsByClass02 §7.1 状态改 "✅ 已有"Grade.score string→Float 转换规则补 §3.3 | ai05 修 02 §7.1 + §3.3 |
| 009 | ai-allocation iam 责任方 ai02 → ai06 | ✅ 修正为 ai06iam 现归属 ai06ai-allocation §3.2 确认) | ai05 修 01/02 引用 |
| 010 | 02 缺 ADR/NFR/容量规划/威胁建模 | ✅ P6 硬化阶段补全(当前不阻塞 P4 实施) | ai05 P6 补全 |
### 20.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------- |
| 01 文档定位 | 历史快照保留原样02 为权威源 | 避免回写成本01 标注"阶段 1 历史快照,以 02 为准" |
| ChildGuard TTL | 30s + 主动失效(统一三处) | §9 #2 + §13 #7 已调整§3.1.1 表格勘误 |
| 契约引用 | I6非 I3ISSUE-047 编号虚构,删除 | coord-final-decisions §1 I6 |
| C6 依赖图同步 | coord 补 004 §4 + matrix.md §1PBFF → IAM + CoreEdu + DataAna + Msg | C6 仲裁 |
| parent-portal 消费方式 | GraphQL`POST /api/v1/parent/v1/graphql`),非 REST | U3 仲裁 + parent-bff 02 §4.1 不实现 REST |
| proto 包名 | `next_edu_cloud.<domain>.v1`(全引用补前缀) | ARB-011 已裁决 |
| msg.proto Notification.child_id | 补 `string child_id = 9;`(可选字段) | ISSUE-007 家长场景需按孩子过滤通知 |
| ClassService 归属 | core-eduARB-007 已补全 4 RPC | coord 批次 0 补全 |
| Grade.score 类型转换 | BFF response-mapper 做 `Number.parseFloat(score)`,失败抛 BFF_PARENT_BAD_GATEWAY | ai05 建议 |
| iam 责任方 | ai06非 ai02 | ai-allocation §3.2 |
### 20.4 ISSUE-005 跨模块契约冲突处理
**冲突**parent-portalai1501 文档 §3.1 按 REST 消费 parent-bff但 parent-bff 02 §4.1 明确"不实现 REST 业务端点"。
**coord 仲裁**:按 project_rules §14.4 跨模块变更顺序处理:
1. parent-bff 契约已定义GraphQL `POST /api/v1/parent/v1/graphql`
2. coord 协调 ai15 将 parent-portal 01/02 文档的 parent-bff 消费契约从 REST 改为 GraphQL
3. 同步 C4 仲裁iam 路径 `/iam/permissions/effective`(非 `/iam/effective-permissions`
4. parent-portal §3.1 标注 "BFF 对接parent-bffai05 设计)"
### 20.5 ISSUE-007 msg.proto Notification 字段补全
coord 协调 ai10 在 msg.proto Notification message 补字段:
```proto
message Notification {
string id = 1;
string user_id = 2;
string type = 3;
string title = 4;
string content = 5;
string channel = 6;
bool is_read = 7;
int64 created_at = 8;
string child_id = 9; // 新增:关联孩子 ID可选非家长通知为空
}
```
> parent-bff GraphQL `Notification.childId` 映射自此字段。ai10 在 msg 02 文档同步补字段说明。
### 20.6 ISSUE-008 ClassService + Grade.score 处理
**ClassService**coord 已在 ARB-007 补全 core_edu.proto ClassService 4 RPCGetClass/GetClassesByTeacher/BatchGetClasses/ListStudentsByClass。parent-bff 02 §7.1 状态从 "❌ 待补" 改为 "✅ 已有"。
**Grade.score 类型转换**parent-bff 02 §3.3 DTO 映射表补转换规则说明:
- `core_edu.v1.Grade.score`string→ GraphQL `Grade.score`Float!
- BFF response-mapper 执行 `Number.parseFloat(score)`
- 转换失败NaN`BFF_PARENT_BAD_GATEWAY` + i18n key `error.bffParent.bad_gateway`
### 20.7 ai05 执行项
1. 02 §3.1.1 ChildGuard TTL 改为 30sISSUE-002 勘误)
2. 02 §3.3 DTO 映射表补 `next_edu_cloud.` 前缀ISSUE-006
3. 02 §3.3 补 Grade.score string→Float 转换规则ISSUE-008
4. 02 §7.1 ClassService.GetClass 状态改 "✅ 已有"ISSUE-008ARB-007 已补全)
5. contract.md §2.1 引用 I3 → I6 修正ISSUE-003
6. 01 §7.1/§7.3 + 02 §7.3 #1 责任方 ai02 → ai06ISSUE-009
7. 01 文档头部标注"阶段 1 历史快照,以 02 为准"ISSUE-001
8. P6 硬化阶段补 02 ADR/NFR/容量规划/威胁建模ISSUE-010非阻塞
### 20.8 coord 执行项
1. 补全 004 §4 服务依赖图:加 `PBFF --> DataAna` + `PBFF --> Msg`ISSUE-004C6 仲裁同步)
2. 补全 matrix.md §1 服务依赖矩阵:加 `PBFF --> DataAna` + `PBFF --> Msg`ISSUE-004
3. 协调 ai10 在 msg.proto Notification 补 `child_id = 9` 字段ISSUE-007
4. 协调 ai15 将 parent-portal 01/02 改为 GraphQL 消费 parent-bffISSUE-005跨模块变更
5. 确认 ClassService 已在 ARB-007 补全ISSUE-008 已覆盖)
---
## §21 ARB-019student-portal 模块 7 项 ISSUE 仲裁
### 21.1 背景
ai14 在 [student-portal_issue.md](./objections/student-portal_issue.md) 提请 7 项异议,涉及 GraphQL endpoint 路径、schema 文件存放位置、考试防作弊策略、主观题粘贴策略、附件上传协议、实时事件命名、DataScope L0 强制执行层。coord 对照 [student-portal_contract.md](./contracts/student-portal_contract.md) v2 + [student-bff_contract.md](./contracts/student-bff_contract.md) v2 + ARB-001/ARB-002/ARB-014 逐条仲裁。
### 21.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ------ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| 014-01 | GraphQL endpoint 路径不一致 | ✅ 统一为 `POST /api/v1/student/graphql`(对齐 matrix.md §5 + ARB-014 方案 A 双 /v1 前缀) | ai14 修 contract.md §2.3 路径 + ai01 确认路由 |
| 014-02 | student-bff GraphQL schema 存放位置不一致 | ✅ 统一为 `packages/shared-ts/contracts/graphql/student-bff.schema.graphql`(对齐 president §2.17 + ARB-016/017 | ai04 创建并维护 |
| 014-03 | 考试作答页全屏策略与防作弊检测边界 | ✅ P3 不强制全屏 + visibilitychange 仅记录 + 多标签警告不阻止 + 走 student-bff GraphQL mutation `recordExamViolation` | ai14 + ai04 |
| 014-04 | 主观题粘贴策略(防作弊 vs 学生体验) | ✅ 客观题禁止 + 主观题允许记录 + 作文题允许不记录;复用 recordExamViolationtype=PASTE | ai14 + ai04 |
| 014-05 | 作业附件上传协议 | ✅ 方案 Aapi-gateway REST `POST /api/v1/student/upload` → 对象存储 → GraphQL mutation 提交 URL | ai01 路由 + ai04 mutation 接受 attachmentUrls |
| 014-06 | 考试延长/题目重排等实时事件命名 | ✅ ai08 发布 ExamExtended + ExamForceSubmitted题目重排 P3 不实现 P4 评估 | ai08 发布 + ai10 推送 |
| 014-07 | 学生端 DataScope L0 边界强制执行层 | ✅ 方案 Astudent-bff Resolver 从 JWT x-user-id 提取 studentId前端 query 不传 studentId | ai14 修 query 设计 + ai04 实现 |
### 21.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ---------------- | ------------------------------------------------------------------------- | --------------------------------------------- |
| GraphQL endpoint | `POST /api/v1/student/graphql`(双 /v1 前缀,对齐 ARB-014 方案 A | matrix.md §5 + ARB-014 §16.4 |
| schema 文件路径 | `packages/shared-ts/contracts/graphql/student-bff.schema.graphql` | president §2.17 + ARB-017 §19.3 |
| 全屏策略 | P3 推荐不强制(提示"建议全屏作答"P4 基于教师反馈评估升级 | 防止误伤合法场景 |
| 离开页面策略 | visibilitychange hidden 仅记录,累计 3 次警告教师端可见;不自动提交 | 误触发风险高 |
| 多标签检测 | BroadcastChannel 警告 + 记录,不阻止作答 | 合法场景如查词典 |
| 防作弊事件上报 | student-bff GraphQL mutation `recordExamViolation(examId, type, payload)` | GraphQL 统一入口;不走 push-gateway |
| 粘贴策略分层 | 客观题禁止 / 主观题允许记录 / 作文题允许不记录 | 防作弊与学生体验平衡 |
| 附件上传协议 | api-gateway REST + 对象存储 + GraphQL mutation 提交 URL | GraphQL 不适合大文件REST + 对象存储业界通用 |
| 实时事件命名 | ExamExtended + ExamForceSubmittedai08 发布到 `edu.exam.events` topic | 事件命名规范 `<Aggregate>.<Action>` |
| 题目重排 | P3 不实现题目顺序固定P4 评估实时重排需求 | 降低 P3 复杂度 |
| DataScope L0 | student-bff Resolver 层从 JWT 强制过滤(方案 A前端不传 studentId | 前端无法绕过gRPC 层重新校验 |
### 21.4 ISSUE-014-03 防作弊策略详情
**全屏 API**P3 不强制(提示"建议全屏作答"P4 评估是否升级为强制(基于教师反馈)
**visibilitychange 策略**
- hidden 触发时仅记录(不自动提交)
- 累计 3 次警告后教师端可见(走 `recordExamViolation` mutation 上报)
- 避免误伤合法场景(如切到词典查询)
**多标签检测**
- BroadcastChannel 检测到多标签时警告 + 记录
- 不阻止作答(避免误伤)
**事件上报链路**
```
student-portal → POST /api/v1/student/graphql (recordExamViolation mutation)
→ student-bff Resolver
→ core-edu gRPC ExamService.RecordViolationai08 在 P3 补全 RPC
→ 落库 + 教师端可见
```
### 21.5 ISSUE-014-05 附件上传协议详情
**方案 A采纳**
1. 前端:`POST /api/v1/student/upload`multipart/form-data→ api-gateway 鉴权 → 对象存储MinIO/OSS→ 返回 signed URL
2. 前端GraphQL mutation `submitHomework(input: { homeworkId, answers, attachmentUrls: [String!] })` 提交作业 + 附件 URL
3. student-bff Resolver 接收 attachmentUrls 字段,透传给 core-edu
**路由配置**
- api-gateway`/api/v1/student/upload``student-bff:3009/upload`(或直接到对象存储代理)
- 由 ai01api-gateway确认路由配置 + 大小限制(建议 20MB+ 类型白名单(图片/PDF/文档)
### 21.6 ISSUE-014-06 实时事件命名详情
| 事件 | 发布方 | topic | 消费链路 | 阶段 |
| --------------------- | ---------------- | ----------------- | --------------------------------------------------- | ---- |
| ExamExtended | ai08core-edu | `edu.exam.events` | msg 消费 → push-gateway → student-portal 更新倒计时 | P3 |
| ExamForceSubmitted | ai08core-edu | `edu.exam.events` | msg 消费 → push-gateway → student-portal 触发提交 | P3 |
| ExamQuestionReordered | ai08core-edu | `edu.exam.events` | P3 不实现P4 评估 | P4 |
### 21.7 ISSUE-014-07 DataScope L0 强制执行详情
**方案 A采纳**student-bff Resolver 层从 JWT 提取 studentId强制过滤
**ai14 修改 02-architecture-design.md §4.2**
- 移除所有 query 的 `studentId` 参数(如 `myClasses(studentId: ID!)``myClasses`
- 所有 query 改为无参或仅含分页/筛选参数
- 前端不传 studentId无法绕过 L0 边界)
**ai04 实现**
- 所有 student-bff Query Resolver 从 JWT `x-user-id` 提取 studentId
- 强制过滤(`WHERE student_id = :jwtStudentId`
- 不接受前端传入的 studentId 参数GraphQL schema 层不暴露)
### 21.8 ai14 执行项
1. 修 contract.md §2.3:统一路径为 `POST /api/v1/student/graphql`ISSUE-014-01
2. 02 §4.2 GraphQL query 定义:移除所有 `studentId` 参数ISSUE-014-07
3. 02 §14 防作弊策略:补全屏策略 + visibilitychange + 多标签 + 事件上报链路ISSUE-014-03
4. 02 §14 粘贴策略:补客观题/主观题/作文题分层ISSUE-014-04
5. 02 §16 实时事件:补 ExamExtended + ExamForceSubmitted 命名ISSUE-014-06
6. 02 §4.2 mutation 域:确认 recordExamViolation + recordPasteEvent 参数(依赖 ai04 补全)
### 21.9 ai04 执行项
1. 创建 `packages/shared-ts/contracts/graphql/student-bff.schema.graphql`ISSUE-014-02
2. 所有 Query Resolver 从 JWT 提取 studentId不接受前端参数ISSUE-014-07
3. P3 提供 `recordExamViolation(input: RecordExamViolationInput!): RecordExamViolationPayload!` mutationISSUE-014-03
4. P3 提供 `recordPasteEvent` mutation 或复用 recordExamViolationtype=PASTEISSUE-014-04
5. submitHomework mutation 接受 `attachmentUrls: [String!]` 字段ISSUE-014-05
### 21.10 ai01 执行项
1. 确认路由 `/api/v1/student/*``student-bff:3009/*`ISSUE-014-01
2. 确认 `/api/v1/student/upload` 路由配置(大小限制 + 类型白名单ISSUE-014-05
### 21.11 ai08 执行项
1. P3 发布 ExamExtended 事件到 `edu.exam.events` topicISSUE-014-06
2. P3 发布 ExamForceSubmitted 事件到 `edu.exam.events` topicISSUE-014-06
3. P3 补全 ExamService.RecordViolation RPC防作弊违规落库ISSUE-014-03
### 21.12 coord 执行项
1. 确认 matrix.md §5 路径前缀对齐 `/api/v1/student/*`ISSUE-014-01
2. 协调 ai08 补全 ExamService.RecordViolation RPCISSUE-014-03
---
## §22 ARB-020parent-portal 模块 10 项 ISSUE 仲裁
### 22.1 背景
ai15 在 [parent-portal_issue.md](./objections/parent-portal_issue.md) 提请 10 项异议,涉及 01/02 文档 REST 消费与 ARB-001 冲突、MF shared 配置缺 urql、switch-child 端点不一致、登录端点三方不一致、未决决策过时、contract §1.2 误标 HTTP 端点、MF 配置文件位置不一致、GraphQL 路径缺 v1、switchChild Mutation 未明确、iam GetChildrenByParent 缺失。coord 对照 [parent-portal_contract.md](./contracts/parent-portal_contract.md) + [parent-bff_contract.md](./contracts/parent-bff_contract.md) + ARB-001/ARB-002/ARB-018 逐条仲裁。
### 22.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------ |
| 001 | 01/02 文档 REST 消费 parent-bff 与 ARB-001 冲突 | ✅ 统一 GraphQL 消费(对齐 ARB-018 ISSUE-005 跨模块裁决) | ai15 修 01/02 |
| 002 | MF shared 配置缺 urql/graphql/@edu/* | ✅ 补全 7 项 singletonreact/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 |
### 22.3 关键裁决
| 裁决点 | 结论 | 依据 |
| ----------------------- | ----------------------------------------------------------------------- | ----------------------------- |
| parent-portal 消费方式 | GraphQL`POST /api/v1/parent/graphql`),非 REST | ARB-001 + ARB-018 ISSUE-005 |
| MF shared | 7 项 singleton 全补齐(含 urql/graphql/@edu/* | ARB-002 §2.2 |
| switchChild 归属 | parent-bff GraphQL Mutation后端审计+ 前端 Zustand 缓存 | 双层记录,避免状态不一致 |
| 登录端点 | `POST /api/v1/iam/login`REST登录前无 JWT 不能走 GraphQL | matrix.md §5 + ARB-014 方案 A |
| 前端路由分类 | 前端页面路由不进 contract §1.2 HTTP 端点表 | parent-portal 是前端 Remote |
| MF 配置文件 | `apps/parent-portal/next.config.js`NextFederationPlugin | 对齐 teacher-portal Shell |
| GraphQL 路径 | `POST /api/v1/parent/graphql`(双 /v1 前缀,对齐 ARB-014 | ARB-014 + matrix.md §5 |
| iam GetChildrenByParent | ai06 P3 收尾前补全I6 裁决P0 阻塞) | coord-final-decisions §1 I6 |
| mock 数据一致性 | parent-portal mock 与 parent-bff mock 一致student-001 + student-002 | ChildGuard 越权校验依赖 |
### 22.4 ISSUE-003 switchChild 端点裁决详情
**裁决**switchChild 走 GraphQL Mutation对齐 ISSUE-001 GraphQL 消费方式)
**GraphQL schema**ai05 补 parent-bff schema
```graphql
type SwitchChildPayload {
childId: ID!
childName: String!
selectedAt: DateTime!
}
type Mutation {
switchChild(childId: ID!): SwitchChildPayload!
}
```
**后端职责**parent-bff
- 记录选中子女用于审计(写 Redis `parent:selected:{parentId}` TTL 30s
- ChildGuard 校验基于 iam.GetChildrenByParent 返回列表
**前端职责**parent-portal
- Zustand store 缓存当前选中子女(`selectedChildId`
- localStorage 持久化(避免刷新丢失)
- 切换子女时同时调 mutation后端审计+ 更新 Zustand
### 22.5 ISSUE-009 switchChild Mutation 归属裁决
**裁决**parent-bff 提供 `switchChild` Mutation后端记录审计同时前端 Zustand + localStorage 缓存
**理由**
1. 纯前端方案无法记录审计日志(谁在何时切换了哪个子女)
2. 后端记录用于异常行为检测(频繁切换可能暗示越权尝试)
3. 前端缓存提升用户体验(刷新不丢失选中状态)
4. 双层记录:后端审计 + 前端缓存Redis TTL 30s 与 ChildGuard 对齐
### 22.6 ISSUE-010 iam GetChildrenByParent P0 阻塞处理
**裁决**ai06 在 P3 收尾前补全I6 裁决),补全前用 mock
**mock 数据要求**
- 返回固定 2 个孩子:`student-001`(李同学)+ `student-002`(李妹妹)
- 与 parent-bff mock 数据一致ChildGuard 校验依赖)
- parent-portal 启动时校验 myChildren 返回的 user_id 与下游查询的 student_id 一致性
**补全时间点**
- ai06 P3 收尾前parent-portal P4 启动前)
- coord 在 workline.md §4 跟踪 ai06 进度
### 22.7 ai15 执行项
1. 01 §3.1 + 02 §4.1REST → GraphQL 消费ISSUE-001
2. 02 §1.2 MF shared补齐 7 项 singletonISSUE-002
3. 01 §3.1 + 02 §2.2/§4.1switch-child → GraphQL Mutation `switchChild`ISSUE-003
4. contract.md §2.3:登录端点改为 `POST /api/v1/iam/login`ISSUE-004
5. 02 §11.3 #2:移除未决项,标注"已裁决:见 ARB-001"ISSUE-005
6. contract.md §1.2:改为"无(前端 Remote不对外提供 HTTP API"ISSUE-006
7. contract.md §1.6MF 配置文件改为 `apps/parent-portal/next.config.js`ISSUE-007
8. contract.md §2.3 + §2.4GraphQL 路径改为 `POST /api/v1/parent/graphql`ISSUE-008
9. 前端实现 `useChildSwitcher` hook调 mutation + Zustand + localStorageISSUE-009
10. mock 数据与 parent-bff 一致student-001 + student-002ISSUE-010
### 22.8 ai05 执行项
1. parent-bff GraphQL schema 补 `switchChild(childId: ID!): SwitchChildPayload!` MutationISSUE-003/009
2. switchChild Resolver写 Redis `parent:selected:{parentId}` TTL 30s + 审计记录
### 22.9 ai06 执行项
1. P3 收尾前补全 iam GetChildrenByParent RPC + iam_student_guardians 表ISSUE-010I6 裁决)
### 22.10 coord 执行项
1. 协调 ai05 补 switchChild Mutation schemaISSUE-003/009
2. 跟踪 ai06 GetChildrenByParent 补全进度ISSUE-010P0 阻塞)
3. 确认 matrix.md §5 路径前缀对齐 `/api/v1/parent/*`ISSUE-008
---
## §23 ARB-021admin-portal 模块 7 项 ISSUE 仲裁
### 23.1 背景
ai16 在 [admin-portal_issue.md](./objections/admin-portal_issue.md) 提请 7 项异议,涉及 01/02 文档归属错误ai07→ai16、端口错误3003→4003、通信协议与 ARB-001/002 不一致、遗漏审计日志与学校设置、teacher-bff 缺 admin 命名空间 schema、推送策略与同类 portal 不一致、matrix.md §4 将 admin-portal 列为 Kafka 直消费方。coord 对照 [admin-portal_contract.md](./contracts/admin-portal_contract.md) + ARB-001/ARB-002 逐条仲裁。
### 23.2 仲裁结论
| ISSUE | 标题 | 仲裁结论 | 执行方 |
| ----- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| 001 | 01/02 模块文档归属错误ai07 → ai16 | ✅ 修正为 ai16ai07 产出视为历史草稿 | ai16 修 01/02 头部 |
| 002 | 01/02 端口错误3003 → 4003 | ✅ 确认 admin-portal 端口 4003同步更新 full-stack-runbook §2.1 补齐 4 个 portal 4000 段 | ai16 修 01/02 + coord 修 runbook |
| 003 | 01/02 通信协议与 ARB-001/002 不一致REST → GraphQL | ✅ 统一 GraphQL`POST /api/admin/graphql` → teacher-bff admin 命名空间);删除 useApi/ApiClient | ai16 修 01/02 全文 |
| 004 | 01/02 遗漏审计日志与学校设置 | ✅ 视口补齐为 11 个dashboard/users/roles/permissions/viewports/organization/classes/teachers/students/audit-logs/system | ai16 修 01/02 |
| 005 | teacher-bff 缺 admin 命名空间 GraphQL schema | ✅ ai03 在 P6 启动前补齐 teacher-bff admin 命名空间 schema参照 contract §2.4 | ai03 补 schema |
| 006 | 01/02 推送策略与同类 portal 不一致(轮询 → WebSocket | ✅ admin-portal 接入 push-gateway WebSocket审计告警/异常登录/系统异常);保留轮询仅用于监控指标 | ai16 修 01/02 |
| 007 | matrix.md §4 将 admin-portal 列为 Kafka 直消费方 | ✅ 修正为 teacher-bffadmin-portal 经 teacher-bff 间接消费链路iam → Kafka → teacher-bff → GraphQL → admin-portal | coord 修 matrix.md §4 |
### 23.3 关键裁决
| 裁决点 | 结论 | 依据 |
| --------------------- | ------------------------------------------------------------------------- | ----------------------------------- |
| 模块归属 | ai16非 ai07ai07 产出视为历史草稿 | ai-allocation §5 |
| 端口 | 4003非 30033003 与 teacher-bff 冲突) | matrix.md §1 + ai-allocation §5 |
| 通信协议 | GraphQL`POST /api/admin/graphql`),非 REST | ARB-001 + ARB-002 |
| GraphQL 端点路径 | `POST /api/admin/graphql`(对齐 contract §2.3,非双 /v1 前缀) | admin 走 teacher-bff非独立 BFF |
| 视口数量 | 11 个(补齐审计日志 + 学校设置) | ai-allocation §5 + contract §1.2 |
| admin 命名空间 schema | ai03 在 P6 启动前补齐 teacher-bff admin schema | ARB-001 §1.3 P6 新增 admin 命名空间 |
| 推送策略 | WebSocket审计告警/异常登录/系统异常)+ 轮询(监控指标 60s / 统计 5min | 同类 portal 一致 + 低频数据轮询合理 |
| Kafka 消费链路 | iam → Kafka → teacher-bff 消费 → GraphQL auditLogs Query → admin-portal | 前端不直连 Kafka经 BFF 聚合 |
### 23.4 ISSUE-005 teacher-bff admin 命名空间 schema 补全
**裁决**ai03 在 P6 启动前补齐 teacher-bff admin 命名空间 GraphQL schema
**补全范围**(参照 admin-portal contract §2.4
```graphql
# teacher-bff.graphql admin 命名空间部分ai03 在 P6 补齐)
type Query {
# 用户管理
adminUsers(filter: AdminUserFilter, page: PageInput): AdminUserConnection!
adminUser(id: ID!): AdminUser
# 角色权限
adminRoles: [AdminRole!]!
adminPermissions: [AdminPermissionGroup!]!
# 视口配置
adminViewports(scope: ViewportScope): [ViewportItem!]!
# 组织管理
adminOrganization(parentId: ID): [OrganizationNode!]!
# 全局管理
adminClasses(filter: ClassFilter): [Class!]!
adminTeachers(filter: TeacherFilter): [Teacher!]!
adminStudents(filter: StudentFilter): [Student!]!
# 审计日志
auditLogs(filter: AuditLogFilter, page: PageInput): AuditLogConnection!
# 仪表盘
adminDashboard: AdminDashboard!
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
deleteUser(id: ID!): Boolean!
toggleUserStatus(id: ID!): User!
createRole(input: CreateRoleInput!): AdminRole!
updateRolePermissions(id: ID!, permissions: [String!]!): AdminRole!
updateViewport(key: String!, input: UpdateViewportInput!): ViewportItem!
}
```
**存放位置**`packages/shared-ts/contracts/graphql/teacher-bff.graphql`admin 命名空间部分,对齐 ARB-001 §1.3 集中管理)
**就绪信号**
- ai03 P6 启动前完成
- 作为 admin-portal P6 的前置就绪信号
- 更新 matrix.md §3 teacher-bff 行的 schema 文件状态
### 23.5 ISSUE-006 推送策略裁决详情
**裁决**admin-portal 接入 push-gateway WebSocket + 保留轮询低频数据
**WebSocket 消费场景**
- 审计告警(异常权限变更、敏感操作)
- 异常登录(非工作时间登录、异地登录)
- 系统异常(服务健康检查异常、资源告警)
**轮询保留场景**
- 监控指标60s 间隔Prometheus 数据)
- 统计数据5min 间隔,全校统计)
**实现**
- `ws://push-gateway:8081/ws`(与同类 portal 一致)
- JWT 鉴权
- 事件类型:审计告警 / 异常登录 / 系统异常
### 23.6 ISSUE-007 Kafka 消费链路修正
**裁决**matrix.md §4 该行消费方更正为 teacher-bffadmin-portal 经 teacher-bff 间接消费)
**实际链路**
```
iam → Kafka edu.iam.audit.created → teacher-bff 消费
GraphQL auditLogs Query
admin-portal 消费
```
**修正范围**
- matrix.md §4 第 111 行:`admin-portal``teacher-bff`
- 避免误导架构分层(前端不直连 Kafka
### 23.7 GraphQL 端点路径说明
**admin-portal 路径**`POST /api/admin/graphql`(非双 /v1 前缀)
**与 ARB-014 方案 A 的关系**
- ARB-014 方案 A 适用于独立服务iam/core-edu 等):`/api/v1/<service>/v1/*`
- admin-portal 走 teacher-bff admin 命名空间:`POST /api/admin/graphql`teacher-bff 已有 `/api/v1/teacher/*` 前缀admin 命名空间作为 teacher-bff 子路径)
- 由 ai01 确认 api-gateway 路由:`/api/admin/*``teacher-bff:3003/admin/*`
### 23.8 ai16 执行项
1. 01/02 头部ai07 → ai16分支名更正ISSUE-001
2. 01 §1 + 02 §12.1:端口 3003 → 4003ISSUE-002
3. 01 §3.1 + 02 §1/§4REST → GraphQLuseApi → useGraphQLClientISSUE-003
4. 01 §2.1/§L1 导航/§L2 路由表:补齐 11 个视口(含 audit-logs + systemISSUE-004
5. 01 §3.3 + 02 §5推送策略改为 WebSocket + 轮询低频数据ISSUE-006
6. 02 §11.3:移除已裁决的"GraphQL vs REST"未决项ISSUE-003
### 23.9 ai03 执行项
1. P6 启动前补齐 teacher-bff admin 命名空间 schema参照 §23.4 清单ISSUE-005
2. schema 存放 `packages/shared-ts/contracts/graphql/teacher-bff.graphql` admin 部分
### 23.10 coord 执行项
1. 修正 matrix.md §4 第 111 行:`admin-portal``teacher-bff`ISSUE-007
2. 同步 full-stack-runbook §2.1:补齐 4 个 portal 4000 段端口ISSUE-002
3. 确认 ai03 admin 命名空间 schema 作为 admin-portal P6 前置就绪信号ISSUE-005
4. 协调 ai01 确认 `/api/admin/*``teacher-bff:3003/admin/*` 路由配置
---
## §8 仲裁流程说明
### 8.1 提请异议
各 AI 在自己模块的 `objections/[模块名]_issue.md` 中追加异议条目,格式:
```markdown
### ISSUE-[编号]-[AI标识][标题]
- **提请方**aiXX
- **日期**YYYY-MM-DD
- **类型**:契约不明确 / 工作量超批 / 前置依赖缺失 / 编号冲突 / 其他
- **描述**[详细描述问题]
- **建议方案**[AI 的建议]
- **状态**:待 coord 仲裁 / 已裁决(见 coord.md §X
```
### 8.2 coord 仲裁
coord 审阅各 `objections/[模块名]_issue.md`在本文件coord.md追加仲裁章节
```markdown
## §N ARB-XXX[主题]
### N.1 背景
### N.2 仲裁结论
### N.3 关键裁决(表格)
### N.4 相关 AI 执行项
```
### 8.3 状态同步
- 仲裁完成后coord 在对应 `objections/[模块名]_issue.md` 中更新状态为"已裁决(见 coord.md §N"
- coord 在 [workline.md](./workline.md) §8 就绪信号跟踪表中更新进度
### 8.4 目录结构
```
issues/
├── coord.md # 本文件(仲裁汇总)
├── workline.md # 总工作安排
├── matrix.md # 上下游对接总矩阵
├── objections/ # 各模块问题/异议
│ ├── [模块名]_issue.md
│ └── cross_issue.md # 跨模块问题
├── worklines/ # 各模块工作排期
│ └── [模块名]_workline.md
└── contracts/ # 各模块对接契约
└── [模块名]_contract.md
```
---
## §9 历史仲裁(已迁移)
以下仲裁已在此前完成,原始记录见 [coord-final-decisions.md](../coord-final-decisions.md) 和 [president-final-rulings.md](../president-final-rulings.md)
- I1-I8iam P2 契约coord-final-decisions.md §1
- F1-F9BFF 设计裁决coord-final-decisions.md §2
- G1-G3Gateway 裁决coord-final-decisions.md §3
- N1-N3content 裁决coord-final-decisions.md §4
- 总裁裁决 70+ 项president-final-rulings.md §1-§5
本文件仅记录**新流程启动后**2026-07-09 起)的仲裁。