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
1635 lines
124 KiB
Markdown
1635 lines
124 KiB
Markdown
# 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-001:teacher-bff GraphQL schema 第一版
|
||
|
||
### 1.1 背景
|
||
|
||
全并行启动前,需仲裁 teacher-bff GraphQL schema 第一版,作为 ai03(teacher-bff)和 ai13(teacher-portal)的共同契约。
|
||
|
||
数据源:ai03 的 [02-architecture-design.md §5](../../services/teacher-bff/docs/02-architecture-design.md#L503) 提供了目标态 schema(P4),但 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 可实现的 Query(iam 已就绪),Mutation 延后到 P3
|
||
# 修订(ARB-016 §18):admin 命名空间 P2 预留 schema 占位(总裁 §5.1 + §7.3 裁决优先级 president > coord)
|
||
# 修订(ARB-016 §18):schema 文件名统一为 <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!
|
||
}
|
||
|
||
# ============ Query(P2 仅读,无 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 → P3(core-edu 就绪后)
|
||
# - classPerformance / studentWeakness / learningTrend → P4(data-ana 就绪后)
|
||
# - notifications → P5(msg 就绪后)
|
||
# - 所有 Mutation → P3+
|
||
# - Subscription → P6+ 评估
|
||
|
||
# ============ admin 命名空间(P2 预留 schema 占位,P6 实现) ============
|
||
# 总裁 §5.1:admin-portal 复用 teacher-bff,admin 命名空间 P2 预留 schema 占位
|
||
# P2 仅声明类型骨架,Resolver 返 null;P6 实现(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 / class(5 个) | 仅依赖 iam(P2 就绪),classes 数据从 iam gRPC 获取(总裁 §3.5) |
|
||
| P2 Mutation 范围 | **无**(P2 纯读) | Mutation 依赖 core-edu(P3),P2 无下游可写 |
|
||
| DataLoader | dashboard 内 classes 列表用 DataLoader | N+1 防御(ai03 §5.1 第 4 条) |
|
||
| 复杂度限制 | depth ≤ 7,cost ≤ 1000 | ai03 §5.1 第 5 条 |
|
||
| admin 命名空间 | **P2 预留** schema 占位(声明 admin Query/Mutation 类型骨架,Resolver 返 null),P6 实现 | 总裁裁决 §5.1 + §7.3(裁决优先级 president > coord,修正原 ARB-001 "P2 不包含") |
|
||
| DataScope 枚举 | SELF / CLASS / GRADE / SCHOOL / SUBJECT / ALL(SUBJECT 替代 DISTRICT) | coord DataScope 6 级统一 |
|
||
| 错误响应 | ActionState 信封(success/errors/data) | coord-final-decisions F9 |
|
||
| 降级模式 | success=true + error=null + data 内 degraded 字段 | 总裁裁决 §3.4 方案 B |
|
||
|
||
> **修订记录**(ARB-016 §18,2026-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 Resolver(dashboard / viewports / me / classes / class)
|
||
4. dashboard Resolver 并行调用 iam(3 RPC)+ iam.classesByTeacher(1 RPC),用 DataLoader 防御 N+1(总裁 §3.5:classes 数据从 iam gRPC 获取)
|
||
5. 实现 ActionState 信封 + 降级模式(方案 B)
|
||
6. P2 预留 admin 命名空间 schema 占位(声明类型骨架,Resolver 返 null;P6 实现见 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-002:MF Shell 暴露清单
|
||
|
||
### 2.1 背景
|
||
|
||
全并行启动前,需仲裁 teacher-portal 作为 MF Shell 暴露哪些模块给 Remote(student/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. GraphQLProvider(urql 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 shared(singleton)配置**:
|
||
|
||
```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 暴露 GraphQLProvider,Remote 复用 | 总裁 §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 不走 MF(Shell 独占 `/login`) | 登录是认证前提,MF 依赖认证 |
|
||
|
||
### 2.4 ai13 执行项
|
||
|
||
1. teacher-portal `next.config.js` 添加 NextFederationPlugin(exposes + 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-003:iam 模块 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/SELF(SUBJECT 替代 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 + gRPC),ai06 回写 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/SELF(6 级) | president §3.2 P2.2;SUBJECT 替代 DISTRICT(K12 学科级更实用) |
|
||
| 双入口策略 | REST `/iam/v1/*` 供 gateway 透传 + gRPC 50052 供 BFF 聚合 | president §2.16 |
|
||
| iam.proto 补全 | 12 RPC(contract.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.0(12 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 → SUBJECT(ISSUE-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/children(I6 裁决)
|
||
|
||
### 3.5 coord 执行项
|
||
|
||
1. 补全 iam.proto 至 12 RPC(ARB-007,批次 0)
|
||
2. 补全 events.proto UserEvent/RoleEvent/AuditEvent + schema_version(ARB-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 §4:iam topic 已为 `edu.iam.*`(核查无需改);补 DataScope 枚举说明
|
||
|
||
---
|
||
|
||
## §4 ARB-004:core-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-006:AttendanceEvent + 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 RPC(ClassService 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/graded(exam + homework 一致) | 统一初始状态为 not_submitted |
|
||
| GraphQL 枚举映射 | DRAFT/PUBLISHED/IN_PROGRESS/GRADING/GRADED/ARCHIVED/CANCELLED;NOT_SUBMITTED/SUBMITTED/GRADED | 大写映射,去掉 SCORED |
|
||
| RPC 统计口径 | 27 RPC(P3 全量) | 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 RPC(ARB-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 §2:core-edu 22 RPC → 27 RPC
|
||
5. 修正 matrix.md §4:class.transferred topic 统一为 `edu.teaching.class.transferred`
|
||
6. 修正 ARB-001 GraphQL schema:ExamStatus 去掉 SCORED 加 CANCELLED;SubmissionStatus 去掉 IN_PROGRESS(如有)确认 NOT_SUBMITTED/SUBMITTED/GRADED
|
||
7. 修正 core-edu_contract.md §2.2:UserEvent topic 从 `edu.identity.user.*` 改为 `edu.iam.user.events`(与 iam ISSUE-003 仲裁一致,聚合 topic 风格)
|
||
|
||
---
|
||
|
||
## §5 ARB-005:content 模块 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 RPC(Textbook 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 main,post-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 标 P5;Neo4j Sync Worker 输入仅 Outbox 事件;P4 移除 safeCreateNode 同步写 | ai09 |
|
||
|
||
### 5.3 关键裁决
|
||
|
||
| 裁决点 | 结论 | 依据 |
|
||
| ------------------------ | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||
| REST 端点风格 | query 参数(`GET /knowledge-points?chapterId=`) | RESTful 规范 + 与 design doc 一致 |
|
||
| 事件 topic 策略 | 聚合 topic + action 字段(4 topic:textbook/chapter/knowledge_point/question) | 与 matrix.md / events.proto ClassEvent 模式一致;减少 topic 数量 |
|
||
| RPC 总数 | 21(TextbookService 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 聚合 topic(textbook/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 main,post-commit review)"
|
||
2. 修改源码 schema:questions.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_version(ARB-006,批次 0)
|
||
2. 修正 matrix.md §2:content 18 RPC → 21 RPC
|
||
3. 修正 matrix.md §4:补登记 edu.content.textbook.events + chapter.events(共 4 聚合 topic)
|
||
|
||
---
|
||
|
||
## §6 ARB-006:events.proto 补全(跨 iam/core-edu/content)
|
||
|
||
### 6.1 背景
|
||
|
||
iam ISSUE-002、core-edu ISSUE-002、content ISSUE-002/003 共同指向 events.proto 不完整。当前 events.proto 仅定义 4 个 message(ClassEvent/ExamEvent/HomeworkEvent/GradeEvent),缺 iam 的 UserEvent/RoleEvent/AuditEvent、core-edu 的 AttendanceEvent、content 的 TextbookEvent/ChapterEvent/KnowledgePointEvent/QuestionEvent,且所有 message 缺 schema_version 字段,文件头注释仍用旧 topic 命名。
|
||
|
||
### 6.2 仲裁结论
|
||
|
||
coord 在批次 0(P2 启动前)补全 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 |
|
||
|
||
**同时**:
|
||
|
||
- 所有现有 message(ClassEvent/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-007:proto 契约补全汇总(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 RPC(Logout/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.proto(ARB-006,7 个新 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-008:msg 模块 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/003);004 待 coord 同步 events.proto 注释(ARB-006 已覆盖);005 待 coord 修正 004 §4.1 PushGW 方向 | coord |
|
||
| 006 | events.proto GradeEvent 缺 class_id + 全部事件缺 student_ids[] | ✅ coord 补全:GradeEvent 补 class_id;Exam/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-013):msg 采用具体动作 topic(`edu.notify.notification.sent` 等,与 core-edu 策略一致) | coord |
|
||
| 009 | RPC 数量超预算(17 vs 13) | ✅ 采用方案 A:维持 13 RPC 预算,裁剪 4 RPC(BatchSendNotification/GetUnreadCount/BatchMarkAsRead/MarkAllAsRead 降级为 REST only) | ai10 |
|
||
| 010 | markAsRead 权限点不一致 | ✅ 以 02 文档 §6.1 为准:`MSG_NOTIFICATION_READ`(非 MANAGE) | ai10 |
|
||
| 011 | DB→ES 降级方向与 ai-allocation 相反 | ✅ 采用双向降级:ES 故障→DB LIKE;DB 故障→ES 只读(仅读操作可降级,写操作必须等 DB 恢复) | ai10 |
|
||
| 012 | 缺 DLQ 与三层幂等防线 | ✅ 非阻塞,ai10 自行补充设计文档(§3.1 补 msg_idempotency 表 + §5.5 三层幂等 + §5 DLQ 设计) | ai10 |
|
||
| 013 | events.proto 缺 4 类 message | ✅ coord 补全(见 §13 ARB-011:MasteryEvent/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 总数 | 13(NotificationService 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 LIKE;DB 故障→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.proto(ARB-011:NotificationEvent + MasteryEvent + GradeEvent 补 class_id + 全部事件补 student_ids[])
|
||
2. 修正 004 §4.1 PushGW 方向表述为"Msg → push-gateway (gRPC)"
|
||
3. 修正 matrix.md §4:msg topic 改为 `edu.notify.notification.*` 具体动作 topic
|
||
|
||
---
|
||
|
||
## §11 ARB-009:data-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 RPC(ARB-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 RPC(4 端 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 RPC(ARB-012,批次 0)
|
||
2. 补全 events.proto AIUsageEvent + MasteryEvent(ARB-011,批次 0)
|
||
3. 补全 iam.proto GetEffectiveDataScope(ARB-007 已覆盖)
|
||
4. 补全 004 §7.2(补登 6 个 topic + CDC 命名规范)/§1.2(端口列)/§4.1(gRPC 启用阶段矩阵)/§12.2(派生数据事件 Outbox 豁免条款)
|
||
5. 更正 coord-cross-review.md §8.2 状态
|
||
6. 修正 matrix.md §4:data-ana topic 改为 `edu.insight.*`
|
||
|
||
---
|
||
|
||
## §12 ARB-010:ai 模块 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 不同步 | ✅ 统一为 50058(port-allocation.md §7 为准);coord 修 matrix.md | coord |
|
||
| 02 | ai 用量事件 topic 三义未决 | ✅ 统一为 `edu.ai.usage`(见 §15 ARB-013) | coord |
|
||
| 03 | ai.proto 待补全 | ✅ P5 目标 6 RPC(Chat/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 | 备课工作流 Temporal(P6 决策点) | ✅ P5 用 BackgroundTasks + Redis;P6 由 coord 评估 Temporal 引入(roadmap 标注 P6 决策点) | ai12 P5 + coord P6 |
|
||
| 07 | iam GetEffectiveDataScope 待 P4 补全 | ✅ coord 批次 0 补全 iam.proto 12 RPC(ARB-007 已覆盖) | coord |
|
||
| 08 | proto package 命名不符合 project_rules §5 | ✅ 统一为 `next_edu_cloud.<domain>.v1`(见 §13 ARB-011) | coord |
|
||
| 09 | 响应信封偏离 ActionState | ✅ P5 实施时整改:所有返回值改为 ActionState;degraded 移至 `error.details.degraded` | ai12 |
|
||
|
||
### 12.3 关键裁决
|
||
|
||
| 裁决点 | 结论 | 依据 |
|
||
| ------------- | --------------------------------------------- | ----------------------------------------- |
|
||
| ai gRPC 端口 | 50058 | port-allocation.md §7 为准 |
|
||
| ai RPC 总数 | 6(P5 目标) | 避免 RPC 膨胀;备课状态查询/确认用 HTTP |
|
||
| ai 用量 topic | `edu.ai.usage` | 最简短,符合 `edu.<domain>.<action>` 约定 |
|
||
| proto package | `next_edu_cloud.ai.v1`(保留现状) | 见 §13 ARB-011 |
|
||
| Temporal | P5 不引入(BackgroundTasks + Redis);P6 评估 | 避免过早引入复杂度 |
|
||
| 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 实施时整改 ActionState(main.py 返回值改为 `{success, data, error:{code,message,details,traceId}}`;degraded 移至 `error.details.degraded`)
|
||
3. P5 备课工作流用 BackgroundTasks + Redis(02 文档 §2.4 状态机已设计)
|
||
4. 修正 01/02 文档引用:004 §7.2/§1.2 引用失实,改引 port-allocation.md + coord 仲裁
|
||
|
||
### 12.5 coord 执行项
|
||
|
||
1. 补全 ai.proto 至 6 RPC(ARB-012,批次 0)
|
||
2. 补全 events.proto AIUsageEvent(ARB-011,批次 0)
|
||
3. 修正 matrix.md §2/§8:ai gRPC 端口 50057 → 50058
|
||
4. 在 roadmap 标注 P6 决策点(Temporal 引入评估)
|
||
5. 在 known-issues §2.9 ai 分区记录 ActionState 整改约束
|
||
|
||
---
|
||
|
||
## §13 ARB-011:events.proto 扩展补全 + proto package 命名统一
|
||
|
||
### 13.1 背景
|
||
|
||
msg ISSUE-013、data-ana ISSUE-002、ai ISSUE-04 共同指向 events.proto 还缺 msg/data-ana/ai 相关 message(ARB-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 个 message:ClassEvent/ExamEvent/HomeworkEvent/GradeEvent(原有 4 + 补字段)+ UserEvent/RoleEvent/AuditEvent/AttendanceEvent/TextbookEvent/ChapterEvent/KnowledgePointEvent/QuestionEvent(ARB-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 个新 message(MasteryEvent/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-012:analytics.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-013:Kafka 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-014:api-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 JWKS(contract 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-015:push-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.2;mTLS 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/Pong,30s 间隔) | 02 文档 §10 |
|
||
|
||
### 17.4 ISSUE-006 Redis 软失败裁决详情
|
||
|
||
**冲突**:
|
||
|
||
- ISSUE-055(president §3.3):Redis 列为"必需依赖",失败返 503
|
||
- ISSUE-058(president §4.3):Redis /readyz "仅告警不阻塞,避免雪崩"
|
||
|
||
**coord 裁决**:以 ISSUE-058 为准(后裁决优先),Redis 对 push-gateway 为**软失败**。
|
||
|
||
**理由**:
|
||
|
||
1. push-gateway 重启不解决 Redis 故障(Redis 是跨实例广播依赖,非本地状态)
|
||
2. Redis 故障时单实例仍能服务本地连接(仅跨实例广播失效)
|
||
3. 重启会丢失本地连接表,加剧雪崩风险
|
||
4. ISSUE-055 的"必需依赖"列表应排除 push-gateway → Redis(Redis 故障不触发 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,不返 503,ISSUE-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 §7:50k → 10w+(ISSUE-003)
|
||
4. 修正 contract.md §1.2:鉴权头统一为 `X-Internal-Token`(ISSUE-002,contract v2 已部分对齐,确认最终)
|
||
5. 修正 004 §7.2 / coord-cross-review:ISSUE-055 必需依赖列表中 push-gateway → Redis 标注"软失败"
|
||
6. ISSUE-005 协调 ai10 确认 msg 审计表覆盖 push-gateway 推送结果字段
|
||
|
||
---
|
||
|
||
## §18 ARB-016:teacher-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.5:P2 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 返 null),P6 实现 | 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` RPC(core-edu gRPC 50053 就绪后) | ARB-007 已补全 ClassService 4 RPC |
|
||
| schema 文件名 | `teacher-bff.schema.graphql`(统一 `<bff-name>.schema.graphql` 格式) | president §2.17 |
|
||
| 裁决优先级 | president > coord(ARB-001 修正为对齐总裁裁决) | 总裁裁决覆盖 coord 仲裁 |
|
||
|
||
### 18.4 ISSUE-002 P2 dashboard 调用链修正
|
||
|
||
**原 ARB-001 §1.4 第 4 条**:
|
||
|
||
> dashboard Resolver 并行调用 iam(3 RPC)+ classes(1 RPC),用 DataLoader 防御 N+1
|
||
|
||
**修正为**:
|
||
|
||
> dashboard Resolver 并行调用 iam gRPC(GetUserInfo + GetViewports + GetEffectiveAccess),classes 列表从 iam 返回数据推导,P3 core-edu gRPC 就绪后切换为 `GetClassesByTeacher` RPC
|
||
|
||
**理由**:
|
||
|
||
1. classes P2 无 gRPC server(classes.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 返 null,ISSUE-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.3:admin 命名空间改为 "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 改 SUBJECT(ARB-003 ISSUE-004 已裁决,需同步 ARB-001)
|
||
|
||
---
|
||
|
||
## §19 ARB-017:student-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.5(ActionState 信封规范)章节 | 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-bff(B8 裁决)
|
||
|
||
### 19.6 coord 执行项
|
||
|
||
1. 补全 004 §11.4(错误码前缀矩阵:GW_/IAM_/CORE_EDU_/BFF_TEACHER_/BFF_STUDENT_/BFF_PARENT_/MSG_/PUSH_/DATA_ANA_/AI_)+ §11.5(ActionState 信封规范:`{success, data, error:{code,message,details,traceId}}` + degraded 放 error.details)
|
||
2. 批次 2 启动前仲裁 student-bff schema 第一版(president §2.2)
|
||
|
||
---
|
||
|
||
## §20 ARB-018:parent-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 RPC(GetClass/GetClassesByTeacher/BatchGetClasses/ListStudentsByClass);02 §7.1 状态改 "✅ 已有";Grade.score string→Float 转换规则补 §3.3 | ai05 修 02 §7.1 + §3.3 |
|
||
| 009 | ai-allocation iam 责任方 ai02 → ai06 | ✅ 修正为 ai06(iam 现归属 ai06,ai-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(非 I3),ISSUE-047 编号虚构,删除 | coord-final-decisions §1 I6 |
|
||
| C6 依赖图同步 | coord 补 004 §4 + matrix.md §1:PBFF → 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-edu(ARB-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-portal(ai15)01 文档 §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-bff(ai05 设计)"
|
||
|
||
### 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 RPC(GetClass/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 改为 30s(ISSUE-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-008,ARB-007 已补全)
|
||
5. contract.md §2.1 引用 I3 → I6 修正(ISSUE-003)
|
||
6. 01 §7.1/§7.3 + 02 §7.3 #1 责任方 ai02 → ai06(ISSUE-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-004,C6 仲裁同步)
|
||
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-bff(ISSUE-005,跨模块变更)
|
||
5. 确认 ClassService 已在 ARB-007 补全(ISSUE-008 已覆盖)
|
||
|
||
---
|
||
|
||
## §21 ARB-019:student-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 学生体验) | ✅ 客观题禁止 + 主观题允许记录 + 作文题允许不记录;复用 recordExamViolation(type=PASTE) | ai14 + ai04 |
|
||
| 014-05 | 作业附件上传协议 | ✅ 方案 A:api-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 边界强制执行层 | ✅ 方案 A:student-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 + ExamForceSubmitted(ai08 发布到 `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.RecordViolation(ai08 在 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`(或直接到对象存储代理)
|
||
- 由 ai01(api-gateway)确认路由配置 + 大小限制(建议 20MB)+ 类型白名单(图片/PDF/文档)
|
||
|
||
### 21.6 ISSUE-014-06 实时事件命名详情
|
||
|
||
| 事件 | 发布方 | topic | 消费链路 | 阶段 |
|
||
| --------------------- | ---------------- | ----------------- | --------------------------------------------------- | ---- |
|
||
| ExamExtended | ai08(core-edu) | `edu.exam.events` | msg 消费 → push-gateway → student-portal 更新倒计时 | P3 |
|
||
| ExamForceSubmitted | ai08(core-edu) | `edu.exam.events` | msg 消费 → push-gateway → student-portal 触发提交 | P3 |
|
||
| ExamQuestionReordered | ai08(core-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!` mutation(ISSUE-014-03)
|
||
4. P3 提供 `recordPasteEvent` mutation 或复用 recordExamViolation(type=PASTE)(ISSUE-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` topic(ISSUE-014-06)
|
||
2. P3 发布 ExamForceSubmitted 事件到 `edu.exam.events` topic(ISSUE-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 RPC(ISSUE-014-03)
|
||
|
||
---
|
||
|
||
## §22 ARB-020:parent-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 项 singleton(react/react-dom/urql/graphql/@edu/ui-tokens/@edu/ui-components/@edu/hooks) | ai15 修 02 §1.2 |
|
||
| 003 | switch-child 端点在 01/02 不一致 | ✅ GraphQL Mutation `switchChild(childId: ID!): SwitchChildPayload!`(走 GraphQL,对齐 ISSUE-001) | ai15 修 01/02 + ai05 补 schema |
|
||
| 004 | 登录端点三方不一致 | ✅ 统一为 `POST /api/v1/iam/login`(对齐 matrix.md §5);登录走 REST,其余走 GraphQL | ai15 修 contract §2.3 |
|
||
| 005 | 02 §11.3 未决决策 #2 已由 ARB-001 裁决 | ✅ 移除未决项,改为"已裁决:见 ARB-001" | ai15 修 02 §11.3 |
|
||
| 006 | contract §1.2 误标前端路由为 HTTP 端点 | ✅ §1.2 改为"无(parent-portal 是前端 Remote,不对外提供 HTTP API)" | ai15 修 contract §1.2 |
|
||
| 007 | contract §1.6 MF 配置文件位置不一致 | ✅ 统一为 `apps/parent-portal/next.config.js`(对齐 02 + teacher-portal Shell) | ai15 修 contract §1.6 |
|
||
| 008 | contract §2.3 GraphQL 路径缺 v1 | ✅ 统一为 `POST /api/v1/parent/graphql`(对齐 matrix.md §5) | ai15 修 contract §2.3 + §2.4 |
|
||
| 009 | parent-bff GraphQL schema 是否含 switchChild | ✅ parent-bff 提供 `switchChild` Mutation(后端记录选中子女用于审计),同时前端 Zustand + localStorage 缓存 | ai05 补 schema + ai15 前端实现 |
|
||
| 010 | iam GetChildrenByParent 缺失(P0 阻塞) | ✅ ai06 P3 收尾前补全(I6 裁决);补全前用 mock(固定 2 个孩子 student-001 + student-002) | ai06 补全 + ai15 mock |
|
||
|
||
### 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.1:REST → GraphQL 消费(ISSUE-001)
|
||
2. 02 §1.2 MF shared:补齐 7 项 singleton(ISSUE-002)
|
||
3. 01 §3.1 + 02 §2.2/§4.1:switch-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.6:MF 配置文件改为 `apps/parent-portal/next.config.js`(ISSUE-007)
|
||
8. contract.md §2.3 + §2.4:GraphQL 路径改为 `POST /api/v1/parent/graphql`(ISSUE-008)
|
||
9. 前端实现 `useChildSwitcher` hook:调 mutation + Zustand + localStorage(ISSUE-009)
|
||
10. mock 数据与 parent-bff 一致(student-001 + student-002)(ISSUE-010)
|
||
|
||
### 22.8 ai05 执行项
|
||
|
||
1. parent-bff GraphQL schema 补 `switchChild(childId: ID!): SwitchChildPayload!` Mutation(ISSUE-003/009)
|
||
2. switchChild Resolver:写 Redis `parent:selected:{parentId}` TTL 30s + 审计记录
|
||
|
||
### 22.9 ai06 执行项
|
||
|
||
1. P3 收尾前补全 iam GetChildrenByParent RPC + iam_student_guardians 表(ISSUE-010,I6 裁决)
|
||
|
||
### 22.10 coord 执行项
|
||
|
||
1. 协调 ai05 补 switchChild Mutation schema(ISSUE-003/009)
|
||
2. 跟踪 ai06 GetChildrenByParent 补全进度(ISSUE-010,P0 阻塞)
|
||
3. 确认 matrix.md §5 路径前缀对齐 `/api/v1/parent/*`(ISSUE-008)
|
||
|
||
---
|
||
|
||
## §23 ARB-021:admin-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) | ✅ 修正为 ai16;ai07 产出视为历史草稿 | 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-bff(admin-portal 经 teacher-bff 间接消费,链路:iam → Kafka → teacher-bff → GraphQL → admin-portal) | coord 修 matrix.md §4 |
|
||
|
||
### 23.3 关键裁决
|
||
|
||
| 裁决点 | 结论 | 依据 |
|
||
| --------------------- | ------------------------------------------------------------------------- | ----------------------------------- |
|
||
| 模块归属 | ai16(非 ai07);ai07 产出视为历史草稿 | ai-allocation §5 |
|
||
| 端口 | 4003(非 3003,3003 与 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-bff(admin-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 → 4003(ISSUE-002)
|
||
3. 01 §3.1 + 02 §1/§4:REST → GraphQL(useApi → useGraphQLClient)(ISSUE-003)
|
||
4. 01 §2.1/§L1 导航/§L2 路由表:补齐 11 个视口(含 audit-logs + system)(ISSUE-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-I8:iam P2 契约(coord-final-decisions.md §1)
|
||
- F1-F9:BFF 设计裁决(coord-final-decisions.md §2)
|
||
- G1-G3:Gateway 裁决(coord-final-decisions.md §3)
|
||
- N1-N3:content 裁决(coord-final-decisions.md §4)
|
||
- 总裁裁决 70+ 项(president-final-rulings.md §1-§5)
|
||
|
||
本文件仅记录**新流程启动后**(2026-07-09 起)的仲裁。
|