Files
Edu/docs/architecture/issues/coord.md
SpecialX dc0a6feec4 docs(docs): coord 仲裁 api-gateway 8 项 ISSUE(ARB-022)
总裁确认采纳方案 A(双 /v1 前缀)。

- coord.md: 新增 §24 ARB-022(api-gateway 8 项 ISSUE 仲裁)
- coord.md: §24.4 ISSUE-003 方案 A 裁决 + 总裁确认记录
- matrix.md: §5 路径前缀修正为双 /v1(方案 A)
- api-gateway_issue.md: §2 状态更新为已裁决

AI: coord
2026-07-10 17:07:15 +08:00

138 KiB
Raw Blame History

coord 仲裁结果汇总

维护者coord协调 AI 维护规则:各 AI 在 objections/[模块名]_issue.md 提请异议 → coord 审阅 → 在本文件写入仲裁结果 关联文档:president-final-rulings.mdai-work-orchestration.mdworkline.mdmatrix.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
ARB-022 2026-07-10 ai01 api-gateway 模块 8 项 ISSUE 仲裁v2 正式版) 已裁决 §24

§1 ARB-001teacher-bff GraphQL schema 第一版

1.1 背景

全并行启动前,需仲裁 teacher-bff GraphQL schema 第一版,作为 ai03teacher-bff和 ai13teacher-portal的共同契约。

数据源ai03 的 02-architecture-design.md §5 提供了目标态 schemaP4但 P2 只需 Must Have 子集。

1.2 仲裁结论

P2 第一版 schema 范围Must Have对应 ai03 P2 工作量分级 Must Have 13 项):

# ============ 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 endpointPOST /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 暴露 GraphQLProviderurql 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 提供了 GraphQL client 单例设计。

2.2 仲裁结论

P2 第一版 MF Shell 暴露清单

// 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配置

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 数量 0P2 暂无 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=falseP2 默认关) ai13 §1.3 回退策略
登录页 P2 不走 MFShell 独占 /login 登录是认证前提MF 依赖认证

2.4 ai13 执行项

  1. teacher-portal next.config.js 添加 NextFederationPluginexposes + shared无 remotes
  2. 创建 src/app/providers.tsxGraphQLProvider 包裹)
  3. AppShell 改造:从 REST /api/v1/teacher/viewports 切换为 GraphQL query viewports
  4. P2 页面dashboard / classes全部用 GraphQL
  5. feature flag NEXT_PUBLIC_MF_ENABLED=falseP2 默认单体路由)

2.5 ai03 执行项(联动)

  1. teacher-bff 暴露 POST /graphql endpoint
  2. 提供GraphQL playground仅开发环境

§3 ARB-003iam 模块 7 项 ISSUE 仲裁

3.1 背景

ai06 在 iam_issue.md §2 提请 7 项异议涉及文档回写、events.proto 缺失、Topic 命名不一致、DataScope 枚举冲突、iam.proto 未补全、AI 身份署名错误、双入口策略冲突。coord 对照 iam_contract.mdv1.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 粒度 聚合 topicedu.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_guardiansI6 裁决)
    • 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.2edu.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 提请 7 项异议,涉及 proto 实际状态与仲裁声称不符、events.proto 未同步、状态命名跨模块不一致、class.transferred topic 不一致、RPC 数量统计口径冲突、7 项设计决策未仲裁、01 文档审计待核对项。coord 对照 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(去掉 SCOREDsubmissions 统一为 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 采用具体动作 topicedu.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(非 scoredsubmissions 统一 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 提请 10 项异议,涉及 REST 端点设计不一致、事件 topic 命名策略冲突、Textbook/Chapter 事件遗漏、RPC 数量三方不一致、core-edu 失效事件无定义、文档 push main 冲突、created_by 迁移风险、缓存/API 版本化缺失、schema 字段缺失、Sync Worker 链路。coord 对照 content_contract.mdv1.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/GradeEventstring 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 提请 15 项异议ISSUE-001005 已有仲裁核查 + ISSUE-006015 新发现),涉及 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 采用具体动作 topicedu.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 策略 具体动作 topicedu.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 改为具体动作 topicedu.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 提请 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.triggereddomain=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 提请 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>.v1next_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 文件仅含标题未填写实质内容(文件截断,仅 2 行),但其 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.jsonTTL 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 使用 zapproject_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 提请 7 项异议,涉及 SSE 端点冲突、内部 API 鉴权命名、容量目标、端点路径、审计表设计、Redis /readyz 冲突、02 文档缺 ADR/NFR。coord 对照 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/pushai02 已自行修复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-KeyX-Internal-TokenINTERNAL_API_KEYINTERNAL_API_TOKENISSUE-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.requestedISSUE-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-TokenISSUE-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 提请 3 项异议,涉及 admin 命名空间 P2 预留与 ARB-001 冲突、dashboard classes 数据来源与调用链冲突、GraphQL schema 文件命名不一致。coord 对照 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 gRPCGetViewports/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.graphqlISSUE-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 §1 提请 4 项新异议STU-001~004涉及 01 文档与 B1/B2/B5 裁决冲突、02 引用不存在的 004 章节、02 §8.3 八项已裁决决策未更新、GraphQL schema 第一版未起草。coord 对照 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 提请 10 项异议,涉及 01 文档未同步、ChildGuard TTL 不一致、契约引用错误、004 依赖图未同步、parent-portal REST vs GraphQL 跨模块冲突、proto 包名缺失、Notification.childId 缺失、ClassService 缺失、责任方过时、02 缺 ADR/NFR。coord 对照 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 消费方式 GraphQLPOST /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 补字段:

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 处理

ClassServicecoord 已在 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.scorestring→ GraphQL Grade.scoreFloat!
  • BFF response-mapper 执行 Number.parseFloat(score)
  • 转换失败NaNBFF_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 --> MsgISSUE-004C6 仲裁同步)
  2. 补全 matrix.md §1 服务依赖矩阵:加 PBFF --> DataAna + PBFF --> MsgISSUE-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 提请 7 项异议,涉及 GraphQL endpoint 路径、schema 文件存放位置、考试防作弊策略、主观题粘贴策略、附件上传协议、实时事件命名、DataScope L0 强制执行层。coord 对照 student-portal_contract.md v2 + 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 防作弊策略详情

全屏 APIP3 不强制(提示"建议全屏作答"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/uploadmultipart/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/uploadstudent-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/graphqlISSUE-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.graphqlISSUE-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 提请 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 + 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 消费方式 GraphQLPOST /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/loginREST登录前无 JWT 不能走 GraphQL matrix.md §5 + ARB-014 方案 A
前端路由分类 前端页面路由不进 contract §1.2 HTTP 端点表 parent-portal 是前端 Remote
MF 配置文件 apps/parent-portal/next.config.jsNextFederationPlugin 对齐 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 schemaai05 补 parent-bff schema

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 switchChildISSUE-003
  4. contract.md §2.3:登录端点改为 POST /api/v1/iam/loginISSUE-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.jsISSUE-007
  8. contract.md §2.3 + §2.4GraphQL 路径改为 POST /api/v1/parent/graphqlISSUE-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 提请 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 + 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 统一 GraphQLPOST /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
通信协议 GraphQLPOST /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

# 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.graphqladmin 命名空间部分,对齐 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-portalteacher-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/graphqlteacher-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-portalteacher-bffISSUE-007—— 已执行(基础设施批次)
  2. 同步 full-stack-runbook §2.1:补齐 4 个 portal 4000 段端口ISSUE-002—— 文件不存在SRE AI 创建时同步
  3. 确认 ai03 admin 命名空间 schema 作为 admin-portal P6 前置就绪信号ISSUE-005—— 已确认
  4. 协调 ai01 确认 /api/admin/*teacher-bff:3003/admin/* 路由配置 —— 见 §24.4 ARB-022 ISSUE-003 裁决

§24 ARB-022api-gateway 模块 8 项 ISSUE 仲裁

24.1 背景

ai01 在 api-gateway_issue.md §1 正式提请 8 项 ISSUEISSUE-001~005/007/008/009ISSUE-006 预留),涉及 matrix.md 契约修正、shared-go 接入、API 版本化路由方案、日志选型、Go 版本不一致、文档过时、错误码 GW_ 前缀 + ActionState 信封。

ARB-014 曾基于 v1 早期 issue.md仅 2 行)从 contract.md v2 内联 4 项 ISSUE 做过初步仲裁;本次基于 ai01 正式提请的 v2 issue.md 重新仲裁ARB-014 中与此冲突的部分以本节为准。

24.2 仲裁结论总览

ISSUE 主题 仲裁结论 影响范围 严重度
ISSUE-001 matrix.md gRPC 矩阵修正 确认(已执行) matrix 已修)
ISSUE-002 shared-go 接入方式 go.work 已含ai01 go.mod 补 github.com/edu-cloud/shared-go 依赖 ai01 P2.1
ISSUE-003 API 版本化路由方案(/v1 前缀位置) 采纳方案 A(双 /v1 前缀) 全模块
ISSUE-004 zap vs slog 选型 shared-go/logger 用 zap(现状保留) ai01 + 所有 Go 服务
ISSUE-005 go.mod 与 Dockerfile 版本不一致 统一为 go 1.22Dockerfile + go.mod + go.work ai01 + ai02
ISSUE-007 01-understanding.md §6 审计表过时 ai01 更新文档 ai01 文档
ISSUE-008 01-understanding.md §7.1 死代码过时 ai01 删除该行 ai01 文档
ISSUE-009 W1/W2 错误码 GW_ + ActionState P2.3 统一修复ai01 已在 workline 列出) ai01 P2.3

24.3 ISSUE-001 matrix.md gRPC 矩阵修正

裁决 已执行(基础设施批次)

  • matrix.md §2 iam "消费方"列已移除 api-gateway(保留 teacher-bff / student-bff / parent-bff
  • matrix.md §7 Mock 策略表已修正为"硬编码 RS256 公钥DEV_MODE→ HTTP JWKS 端点"
  • 依据:总裁 §2.16 裁决第 3 条"gateway 保持 HTTP 透传,不改为 gRPC 客户端"

跨模块影响matrix.md 已修正,其他 AI 不受影响)

24.4 ISSUE-003 API 版本化路由方案(/v1 前缀位置)

裁决采纳方案 A双 /v1 前缀)

⚠️ 严重影响说明:此裁决与总裁 §2.15 裁决第 4 条"避免双 v1"存在冲突。coord 经审查后认为方案 A 更符合实际架构现状,但需明确说明冲突原因与修正范围。

路由方案

前端调用路径 Gateway 路由 proxy 透传目标 下游 Controller 路径
/api/v1/iam/v1/auth/login /api/v1/iam/v1/*path iam:3002 /iam/v1/*path @Controller('v1/iam/auth')
/api/v1/teacher/v1/graphql /api/v1/teacher/v1/*path teacher-bff:3003 /teacher/v1/*path GraphQL /graphqlBFF 无 Controller 分层)
/api/v1/student/v1/graphql /api/v1/student/v1/*path student-bff:3009 /student/v1/*path GraphQL /graphql
/api/v1/parent/v1/graphql /api/v1/parent/v1/*path parent-bff:3010 /parent/v1/*path GraphQL /graphql
/api/v1/admin/v1/graphql /api/v1/admin/v1/*path teacher-bff:3003 /admin/v1/*path GraphQL admin 命名空间

理由

  1. iam_contract.md §2.3 已明确 GET /iam/v1/.well-known/jwks.jsonController 内含 /v1若 Gateway 透传不含 /v1则前端需调用 /api/v1/iam/.well-known/jwks.json(缺服务级 /v1与 iam 实际 Controller 路径不一致
  2. api-gateway_contract.md §1.2.2 v2 已列方案 A(双 /v1且注明"方案 A双 v1"
  3. matrix.md §5 已对齐方案 A/api/v1/teacher/* → 方案 A 下应为 /api/v1/teacher/v1/*
  4. ARB-014 §16.4 已采纳方案 AARB-019/020/021 前端 portal 仲裁均引用方案 A/api/v1/student/v1/graphql 等)
  5. 方案 B 的"避免双 v1"虽符合总裁裁决字面意思,但要求下游 Controller 不加 /v1 前缀,与 iam_contract.md §2.3 实际路径 /iam/v1/.well-known/jwks.json 矛盾

与总裁 §2.15 裁决的冲突说明

  • 总裁 §2.15 第 4 条"避免双 v1"字面要求"Controller 加 /v1Gateway 转发路径不含 /v1"
  • 但总裁 §2.15 第 3 条"Gateway 透传时不改路径"与第 4 条存在内在矛盾:若 Controller 加 /v1Gateway 透传时必然携带 /v1前端调用必然双 /v1
  • coord 裁决:以总裁 §2.15 第 3 条"Gateway 不改路径"为准,接受双 /v1方案 A第 4 条"避免双 v1"在实际执行中无法同时满足第 3 条,故第 4 条不适用
  • 提请总裁复核:若总裁坚持"避免双 v1",需修正 iam_contract.md §2.3 的 Controller 路径(移除 /v1 前缀),并同步修正所有服务的 Controller 路径设计

matrix.md §5 修正

当前 matrix.md §5 路径为 /api/v1/teacher/*(单 /v1需修正为 /api/v1/teacher/v1/*(双 /v1方案 A

修正前 修正后
/api/v1/teacher/* /api/v1/teacher/v1/*
/api/v1/student/* /api/v1/student/v1/*
/api/v1/parent/* /api/v1/parent/v1/*
/api/v1/iam/* /api/v1/iam/v1/*

跨模块影响

  • 前端 4 个 portalai13/ai14/ai15/ai16:文档已统一为双 /v1ARB-019/020/021 已采纳方案 A无影响
  • BFF 层ai03/ai04/ai05GraphQL endpoint 路径 /graphql 不变,仅 Gateway 路由前缀变化BFF 内部无影响
  • iamai06Controller 路径已含 /v1(如 /iam/v1/.well-known/jwks.json),无影响
  • core-edu/content/msg/data-ana/aiController 需加 /v1 前缀(总裁 §2.15 第 1 条"各服务按自身节奏推进"P3-P5 各服务启动时由对应 AI 落实

24.5 ISSUE-002 shared-go 接入方式

裁决go.work 已含 ./packages/shared-go已执行ai01 go.mod 需补 github.com/edu-cloud/shared-go 依赖

现状核查

  • go.work L3-6 已含 ./packages/shared-goISSUE-002 部分已解决)
  • go.mod 未含 github.com/edu-cloud/shared-go(待 ai01 P2.1 接入时补充)

ai01 执行项

  1. go.mod 增加 require github.com/edu-cloud/shared-go v0.0.0go work replace 模式)
  2. P2.1 任务接入 jwks/logger/tracer/env 4 模块
  3. 若 shared-go 模块路径命名与预期不符,提请 coord 仲裁

跨模块影响:无(仅 ai01 自身依赖配置)

24.6 ISSUE-004 zap vs slog 选型

裁决shared-go/logger 用 zap现状保留W3 裁决修正为 zap

现状核查

与 W3 裁决的冲突说明

  • W3 裁决原文"首次实现即用 slog"
  • 但 shared-go/logger 已用 zap 实现,且 zap 在 Go 生态中性能与生态成熟度优于 slog
  • coord 裁决接受现状zapW3 裁决修正为"shared-go/logger 基于 zap 封装ai01 通过 import shared-go/logger 间接使用 zap不直接 import zap"

ai01 执行项

  1. P2.1 任务 import github.com/edu-cloud/shared-go/logger
  2. 替换全部 log.Printflogger.FromContext(ctx).Info/Error/Warn
  3. 涉及文件main.go L70/160/169/176、config.go L38/41、recovery.go L22、circuit-breaker.go L38、tracer.go L25/31/43/51/65/70

跨模块影响

  • ai02push-gateway:同样 import shared-go/logger使用 zap无影响
  • 其他 Go 服务:若后续有 Go 服务,统一通过 shared-go/logger 使用 zap

24.7 ISSUE-005 go.mod 与 Dockerfile Go 版本不一致

裁决:统一为 go 1.22(与 Dockerfile + 01-understanding.md §4 一致)

版本对齐

文件 当前 修正后
Dockerfile L1 golang:1.22-alpine golang:1.22-alpine(不变)
go.mod L3 go 1.25.0 go 1.22
go.work L1 go 1.26.0 go 1.22

理由

  • Dockerfile 1.22-alpine 是实际构建环境,必须以它为准
  • 01-understanding.md §4 声明 Go 1.22
  • go.mod 1.25.0 / go.work 1.26.0 是误升版本,回退到 1.22

ai01 执行项

  1. go.mod L3 改为 go 1.22
  2. go.work L1 改为 go 1.22
  3. 验证 go build ./... 通过

跨模块影响

  • ai02push-gateway:同样需对齐 go 1.22(若 push-gateway go.mod/go.work 版本不一致ai02 同步修正)
  • 其他服务TS/Python 服务无影响

24.8 ISSUE-007 01-understanding.md §6 审计表 metrics 行过时

裁决ai01 更新文档

ai01 执行项

  1. 01-understanding.md §6 审计表 metrics 行:❌ 无⚠️ 端点已注册,缺 7 个业务指标
  2. 01-understanding.md §7.1 issue #1更新为"已注册 /metrics需补 7 个业务指标(见 workline P2.5"

跨模块影响:无

24.9 ISSUE-008 01-understanding.md §7.1 issue #3 死代码引用过时

裁决ai01 删除该行

ai01 执行项

  1. 01-understanding.md §7.1 issue #3 整行删除(死代码 RequestIDMiddleware() + generateUUID() 已修复)

跨模块影响:无

24.10 ISSUE-009 W1/W2 错误码 GW_ 前缀 + ActionState 信封

裁决P2.3 任务统一修复ai01 已在 workline 列出)

修复范围

文件 当前问题 修复后
auth.go 错误码 UNAUTHORIZED/INVALID_TOKEN/INVALID_CLAIMS(无 GW_ 前缀) GW_UNAUTHORIZED/GW_INVALID_TOKEN/GW_INVALID_CLAIMS
ratelimit.go L51-54 {"error":"rate_limited","retry_after":60}(无信封) {"success":false,"error":{"code":"GW_RATE_LIMITED","message":"..."},"retry_after":60}
circuit-breaker.go L55-58 {"error":"circuit_open","retry_after":30}(无信封) {"success":false,"error":{"code":"GW_CIRCUIT_OPEN","message":"..."},"retry_after":30}
recovery.go L24-27 {"error":"internal_error","request_id":"..."}(无信封) {"success":false,"error":{"code":"GW_INTERNAL_ERROR","message":"...","traceId":"..."}}

ActionState 信封规范:见 004 §11.5 ActionState 信封规范coord 基础设施批次已补充)

ai01 执行项

  1. P2.3 任务统一修复 4 个中间件文件
  2. 错误码统一 GW_ 前缀(对齐 contract.md §1.6 错误码清单)
  3. 响应体统一 ActionState 信封(对齐 004 §11.5

跨模块影响:无(仅 ai01 自身代码修复)

24.11 ai01 执行项汇总

任务 ISSUE 阶段 阻塞
go.mod 补 shared-go 依赖 + 接入 jwks/logger/tracer/env ISSUE-002/004 P2.1 P2.1
替换 log.Printf 为 shared-go/logger ISSUE-004 P2.1 P2.1
go.mod/go.work 版本回退到 1.22 ISSUE-005 P2.0 P2.0
01-understanding.md §6/§7.1 文档更新 ISSUE-007/008 P2.0
错误码 GW_ + ActionState 信封统一修复 ISSUE-009 P2.3 P2.3
API 版本化路由方案 A 落实P1 代码迁移到 /v1 前缀) ISSUE-003 P2.7 P2.7

24.12 coord 执行项

  1. matrix.md §2 移除 api-gateway 为 iam gRPC 消费方(基础设施批次已执行)
  2. matrix.md §5 路径前缀修正为双 /v1方案 A—— 本节裁决后立即执行
  3. 004 §11.5 ActionState 信封规范已补充(基础设施批次已执行)
  4. 协调 ai02 同步修正 push-gateway go.mod/go.work 版本到 1.22
  5. 总裁已确认采纳方案 A2026-07-10§2.15 第 4 条"避免双 v1"不再适用

§8 仲裁流程说明

8.1 提请异议

各 AI 在自己模块的 objections/[模块名]_issue.md 中追加异议条目,格式:

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

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

8.2 coord 仲裁

coord 审阅各 objections/[模块名]_issue.md在本文件coord.md追加仲裁章节

## §N ARB-XXX[主题]

### N.1 背景

### N.2 仲裁结论

### N.3 关键裁决(表格)

### N.4 相关 AI 执行项

8.3 状态同步

  • 仲裁完成后coord 在对应 objections/[模块名]_issue.md 中更新状态为"已裁决(见 coord.md §N"
  • coord 在 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.mdpresident-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 起)的仲裁。