Files
Edu/docs/architecture/coord-final-decisions.md

32 KiB
Raw Blame History

Coord 最终方案强制裁决

版本1.0(历史文档) 日期2026-07-09 决策者coord经用户确认 适用范围Edu 项目全部 15 份 AI 设计文档ai01-ai06, ai08-ai16

⚠️ 历史声明:本文件为批次模式时期2026-07-09的 coord 强制裁决记录。项目已于 2026-07-10 切换为全并行开发模式

关联文档:004 架构影响地图 §16ai-allocation.mdproject_rules.md


0. 裁决原则

用户反馈:"前面简略实现后面要重写,完全没必要,直接使用最好的方式工作"

各 AI 设计文档中存在大量"P2 简化 → P3 重构 → P4 再重构"的渐进式过渡方案导致前期代码后期必废弃。coord 裁决如下:

0.1 强制覆盖声明

  • 本文档 > 各 AI 设计文档:凡本文档列出的裁决项,各 AI 设计文档中与之冲突的"中间过渡方案"一律作废,直接采用最终方案
  • 不分阶段:最终方案在服务首次落地时即采用,不得以"阶段未到"为由先实现简化版
  • 回写义务:各 AI 收到本文档后,必须在 3 个工作日内回写自己的 02-architecture-design.md删除所有"中间过渡方案"描述,对齐最终方案

0.2 裁决依据

  • 用户明确指示"直接使用最好的方式"
  • project_rules.md §3.1 已规定企业级规范(如 Dockerfile 多阶段、Zod 验证、GlobalErrorFilter无理由分阶段
  • 黄金模板 services/classes/ 已实现全部最终方案,其他服务对齐即可

1. 通用裁决(适用全部服务)

# 过渡项 禁止的中间方案 强制最终方案 影响服务
G1 Dockerfile "P3 重构"、"P5 重构"、"待落地" 首次实现即多阶段构建builder + runtime 全部
G2 /readyz 探针 "P2 仅返回 ok"、"P3+ 补下游探针" 首次实现即检查全部下游依赖DB SELECT 1 / Redis PING / Kafka 连接 / gRPC 下游可达) 全部
G3 /healthz "P2 改造" 首次实现即 liveness 探针 全部
G4 Logger "待引入 slog"、"console.log → P3 修复" 首次实现即结构化日志TS pino / Go slog / Python structlog禁止 console.log 全部
G5 Metrics "自定义业务指标待实现" 首次实现即 /metrics 端点 + 基础业务指标 全部
G6 Tracer "资源属性待补"、"span 待补" 首次实现即 OTel SDK + OTLP exporter + 完整资源属性 + 全链路 span 全部
G7 Zod 验证 "P2 补全"、"P3 实施中"、"部分 → P4 全 parse" Controller 层首次实现即全量 schema.parse(body/query/params) 全部 TS
G8 GlobalErrorFilter "待落地"、"P4+ 对齐 ActionState" 首次实现即注册 GlobalErrorFilter + 响应信封严格对齐 ActionState 结构 全部
G9 优雅关闭 "P2 补全" 首次实现即 SIGTERM → app.close() → shutdownTracer(),按序关闭 HTTP→DB→Redis→Kafka 全部
G10 DB 连接模式 "const db vs getDb()" 统一 getDb() 函数(对齐 classes 黄金模板) 全部 TS 持 DB 服务
G11 ID 策略 "cuid2 vs randomUUID" 统一 cuid2(对齐 classes 黄金模板) 全部 TS 持 DB 服务
G12 ESM import 缺 .js 后缀 所有相对 import 带 .js 后缀NestJS ESM 模式) 全部 TS
G13 import type 混用 仅用于类型的导入必须 import type 全部 TS
G14 错误码前缀 api-gateway 无前缀 每个服务错误码必须用服务名大写前缀GW_/IAM_/CORE_EDU_/CONTENT_/MSG_/DATA_ANA_/AI_/PUSH_/BFF_TEACHER_/BFF_STUDENT_/BFF_PARENT_/CLASSES_ 全部
G15 错误码子前缀 保留 EXAMS_/HOMEWORK_/GRADES_ 统一用聚合域前缀 CORE_EDU_*,禁止子前缀 前端 + core-edu
G16 Kafka topic 命名 edu.notification.events 抽象名 edu.<domain>.<aggregate>.<action> 具体动作(如 edu.notification.sent 全部
G17 proto 包名 不一致 next_edu_cloud.<domain>.v1 全部

2. BFF 层专项裁决teacher-bff / student-bff / parent-bff

# 过渡项 禁止的中间方案 强制最终方案
B1 API 风格 "P2 REST → P4 GraphQL"、"P3 REST → P4+ GraphQL" P2 起直接 GraphQLGraphQL Yoga + DataLoader
B2 对下游通信 "P2 HTTP fetch → P3+ gRPC"、"P3 HTTP → P3+ gRPC" 首次实现即 gRPC 调用下游iam/core-edu/content/data-ana/msg/ai 全部 gRPC
B3 权限装饰器 "BFF 加 @RequirePermission"、"待仲裁" BFF 豁免 @RequirePermission(权限由 Gateway JWT + 下游服务负责BFF 仅校验 x-user-id 存在
B4 越权防御 "仅 teacher-bff 透传"、"student-bff 待仲裁" 全部 BFF 强制自我越权防御student-bff 比对 userId、parent-bff 校验 childId 绑定列表、teacher-bff 校验 teacherId 与班级关系
B5 错误码前缀 "STUDENT_BFF_ vs BFF_STUDENT_" BFF_TEACHER_ / BFF_STUDENT_ / BFF_PARENT_(统一 BFF_ 前缀)
B6 缓存策略 "不缓存 vs Redis 短缓存" Redis 5-30s 短缓存(对齐 004 §6.2 BFF 混合读策略)
B7 Kafka 订阅 "P3 评估"、"P5 评估" P2-P4 不订阅 Kafka仅同步聚合P5 push-gateway 落地后再订阅
B8 DownstreamClient 抽象 "是否回写 teacher-bff" 回写 teacher-bff,作为 BFF 模式 v2 标准抽象3 个 BFF 统一使用

3. 业务服务专项裁决

3.1 iamai06

# 过渡项 禁止的中间方案 强制最终方案
I1 gRPC server "P2 仅 REST → P3 启用 gRPC" P2 即启用 gRPC server 50052,同时暴露 REST + gRPC
I2 Outbox "iam 自建 → core-edu 落地后回写 shared-ts" 直接建 shared-ts Outbox 工具包iam 首次实现即用
I3 PermissionGuard "本地 ROLE_PERMISSIONS map → DB 驱动" 首次实现即 DB 驱动 + Redis 缓存,废弃本地 map
I4 AuthMiddleware "P2 不注册 → Controller 直读 header" 首次实现即注册 AuthMiddlewareController 通过 @Req() 获取用户上下文
I5 JWT 密钥 "P2 本地文件 → P6 Vault" P2 本地文件IAM_PRIVATE_KEY_PATH / IAM_PUBLIC_KEY_PATHP6 迁 Vault 单列后续
I6 家长-学生关联 "接口缺失 → P3 补" P2 即补全iam_student_guardians 表 + GetChildrenByParent RPC + GET /iam/children RESTP0 阻塞 parent-bff
I7 API 版本化 "待 coord 审查" 采用 /iam/v1/ 前缀*Gateway 同步调整
I8 iam 端点路径 /iam/permissions/effective vs /iam/effective-permissions 统一 GET /iam/permissions/effectiveRESTful 资源路径风格)

3.2 core-eduai08

# 过渡项 禁止的中间方案 强制最终方案
C1 classes 合并 "P3 初期 vs P3 末期" P3 开始前直接合并classes 代码迁移到 core-educlasses 服务下线
C2 gRPC server "P3 启用" P3 首次实现即启用 gRPC server 50053
C3 Kafka console.log "P3 修复" 首次实现即用 logger.info,禁止 console.log
C4 AttendanceService "待 coord 补 proto" P3 首次实现即补全 proto + 实现
C5 GetClassesByTeacher / BatchGetClasses "待新增" P3 首次实现即补全
C6 排课 room_id "P3 实现 vs 预留 vs P6+" P3 预留字段(不实现逻辑,但 schema 含字段)
C7 成绩计算公式 "scope 优先级待定" class > subject > school(越细粒度优先)
C8 作业 grace_period "0 秒 vs 300 秒" 默认 300 秒5 分钟宽限)
C9 schema 强制校验 "P3 JSON Schema vs 文档约束" P3 仅文档约束P6+ 引入 schema registry
C10 exam.submitted 事件 "包含完整 answers vs 仅 submission_id" 仅含 submission_id(避免事件过大)
C11 archived 考试 "物理迁移 vs 软删除 vs P6+" 仅软删除is_archived 字段)

3.3 contentai09

# 过渡项 禁止的中间方案 强制最终方案
N1 gRPC server "gRPC 待实现" P4 首次实现即启用 gRPC server 50054
N2 /readyz "仅 DB → P4 多依赖" 首次实现即检查 DB/Neo4j/Kafka
N3 QuestionService "P5 阻塞待补 proto" P4 即补全 QuestionService proto(不等到 P5
N4 ErrorFilter "错误响应结构待对齐" 首次实现即对齐 ActionState
N5 ChapterService "缺 GetChapter" P4 首次实现即补全

3.4 msgai10

# 过渡项 禁止的中间方案 强制最终方案
M1 gRPC server "gRPC 待实现" P5 首次实现即启用 gRPC server 50056
M2 /readyz "仅 DB → P5 多依赖" 首次实现即检查 DB/ES/Redis/Kafka/PushGateway
M3 ZodError "未处理 → P5 处理" 首次实现即处理 ZodError 分支
M4 调用 push-gateway "gRPC PushService.Push" HTTP POST /internal/pushcoord 仲裁豁免 gRPC
M5 事件 topic "edu.teaching.assignment.*" edu.teaching.homework.*(与 core-edu 发布方一致)

3.5 data-anaai11

# 过渡项 禁止的中间方案 强制最终方案
D1 ErrorFilter "v2 对齐 ActionState" 首次实现即对齐 ActionState
D2 Dockerfile "v2 设计多阶段" 首次实现即多阶段
D3 ClickHouse DDL "待 coord 建目录" 直接建 infra/clickhouse/ddl/
D4 analytics.proto 扩展 "待 coord 审议" P4 即补全4 端 Dashboard + Warning + MasteryDistribution + SubscribeMasteryUpdate Stream RPC
D5 warning.triggered topic "待 coord 登记" 已登记004 §7.2 + events.proto MasteryEvent

3.6 aiai12

# 过渡项 禁止的中间方案 强制最终方案
A1 ErrorFilter "待对齐" 首次实现即对齐 ActionState
A2 Dockerfile "实现阶段需新增" 首次实现即多阶段
A3 gRPC 端口 "待 coord 补登" 已补登 50058(见 infra/port-allocation.md
A4 ai.proto 补全 "待 coord" P5 首次实现即补全 GenerateLessonPlan / StreamGenerateQuestion
A5 AIUsageEvent proto "待 coord" 已补全 events.proto
A6 Prompt 模板存储 "P5 YAML / P6+ DB" P5 直接用 DB 存储(避免后期迁移)
A7 备课工作流 "P5 Redis / P6+ Temporal" P5 用 FastAPI BackgroundTasks + RedisTemporal 引入成本高P6+ 单独评估)
A8 多模态 "P5 文本 / P6+ 多模态" P5 仅文本proto v2 预留字段

3.7 push-gatewayai02

# 过渡项 禁止的中间方案 强制最终方案
P1 gRPC "备选 gRPC PushService" 彻底删除 gRPC 设计,纯 HTTP + WebSocketcoord 仲裁豁免)
P2 X-Internal-Key "→ X-Internal-Token P5 立即" 首次实现即 X-Internal-Token(环境变量 INTERNAL_API_TOKEN
P3 Dockerfile "P5 重构" 首次实现即多阶段
P4 slog "待引入" 首次实现即用 slog
P5 SSE 降级 "P7+ 考虑" 本期仅 HTTP 长轮询预留SSE 不实现
P6 断线重连 "本期仅协议预留" 本期仅协议预留session_id + last_seq 字段P6 实现补推逻辑

3.8 api-gatewayai01

# 过渡项 禁止的中间方案 强制最终方案
W1 错误码前缀 "无前缀" GW_*GW_UNAUTHORIZED 等)
W2 错误信封 "recovery/ratelimit/circuit-breaker 待整改" 首次实现即对齐 ActionState
W3 slog "待引入" 首次实现即用 slog
W4 /readyz "待重构" 首次实现即真实健康检查(轮询下游 /healthz
W5 业务 metrics "待实现" 首次实现即基础业务指标(请求量/延迟/错误率/熔断)
W6 tracer 资源属性 "待补" 首次实现即完整version/env/host
W7 DevMode 防护 "P1 待办" 首次实现即生产防护DEV_MODE 仅非生产环境生效)
W8 per-服务实例熔断 "P6 待办" 保持共享 downstream 熔断per-实例 P6 单独评估

4. 前端 4 portal 专项裁决

# 过渡项 禁止的中间方案 强制最终方案
F1 admin-portal 端口 3003 / 3000 / 4003 三处矛盾 统一 4003
F2 admin-portal MF 配置 teacher_app@localhost:3000 teacher_app@localhost:4000
F3 Web Vitals FID vs INP 混用 统一 INPCWV 2024 标准)
F4 i18n key 命名 bff.error / bffTeacher.error / bffStudent.error 混用 统一 error.<service>.<code_snake>(如 error.iam.invalid_credentials、error.bffTeacher.validation_error
F5 错误码子前缀 parent-portal 保留 GRADES_/HOMEWORK_ 统一删除子前缀,用 CORE_EDU_*
F6 iam 权限端点 /iam/permissions/effective vs /iam/effective-permissions 统一 /iam/permissions/effective
F7 权限点命名风格 TEACHER_DASHBOARD_VIEW / STUDENT_DASHBOARD_READ / GRADES_READ_CHILD 混用 统一 <RESOURCE>_<ACTION>(如 DASHBOARD_VIEW、EXAM_READ、GRADE_READ数据范围用后缀 _OWN/_CHILD如 GRADE_READ_CHILD
F8 packages 归属 "ai07/ai13 维护 vs coord 维护" ai13 维护 ui-tokens/ui-components/hookscoord 仅维护 shared-ts/contracts
F9 GraphQL vs REST "P2-P6 REST未来切 GraphQL" P2 起 BFF 用 GraphQL前端用 urql/apollo
F10 MF 暴露粒度 "AppShell 整体 vs 细粒度" 暴露 AppShell 整体,各 Remote 自行决定内部布局
F11 teacher-portal 归属 "004 §15.1 写 ai07ai-allocation §3.2 写 ai13" ai13 负责 teacher-portalai07 负责 classes 黄金模板)
F12 localStorage token "P6 评估迁移 httpOnly Cookie" P2 用 localStoragehttpOnly Cookie + CSRF Token P6 单独评估)

5. 跨服务契约裁决(一次性补全,不分阶段)

5.1 proto 契约补全coord 负责P2 启动前全部就位)

proto 文件 待补内容 阻塞阶段 完成期限
events.proto 已补全UserEvent/RoleEvent/NotificationEvent/MasteryEvent/AIUsageEvent/KnowledgePointEvent/QuestionEvent 已完成
iam.proto GetViewports / GetEffectivePermissions / GetEffectiveAccess / Logout / GetPublicKey / BatchGetUsers / GetEffectiveDataScope / GetChildrenByParent P2 P2 启动前
core_edu.proto AttendanceService.* / GetClassesByTeacher / BatchGetClasses P3 P3 启动前
content.proto ChapterService.GetChapter / QuestionService.* / TextbookService.ListTextbooks 补全 P4 P4 启动前
analytics.proto GetTeacherDashboard / GetStudentDashboard / GetParentDashboard / GetAdminDashboard / GetWarnings / GetMasteryDistribution / SubscribeMasteryUpdate (stream) P4 P4 启动前
ai.proto GenerateLessonPlan / StreamGenerateQuestion / 字段扩展 P5 P5 启动前
msg.proto BatchSendNotification / GetUnreadCount / BatchMarkAsRead / MarkAllAsRead / RecallNotification + NotificationPreferenceService + NotificationTemplateService + 3 个 message P5 P5 启动前

5.2 接口命名统一

调用方 被调方 统一命名 说明
core-edu content KnowledgeGraphService.GetPrerequisites / GetLearningPath 禁用 ContentService 命名
teacher-bff data-ana GetTeacherDashboard(无 Stats 后缀) 统一命名
msg / student-bff push-gateway HTTP POST /internal/pushbody 含 user_id 豁免 gRPC
ai core-edu ExamService.GetExam 方向ai 调 core-edu非反向

5.3 gRPC server 启用时机

服务 gRPC 端口 启用时机 说明
iam 50052 P2 首次实现即启用(覆盖"P2 仅 REST"
core-edu 50053 P3 首次实现即启用
content 50054 P4 首次实现即启用
data-ana 50055 P4 首次实现即启用
msg 50056 P5 首次实现即启用
ai 50058 P5 首次实现即启用
push-gateway 不启用 豁免 gRPC
BFF3 个) 不暴露 gRPC 仅对下游走 gRPC

6. 待 P6+ 单独评估事项(不阻塞当前阶段)

以下事项不属于"中间过渡方案",属于"未来扩展",保持原状:

# 事项 评估时机
X1 ai 发布 edu.insight.ai.generated / feedback / workflow 3 个新 topic P6+
X2 admin-portal 8 个新 Kafka topic + events.proto message P6 实施时
X3 admin-portal 审计日志/安全事件归属iam vs audit-service P6
X4 ai 备课工作流迁移 Temporal P6+
X5 ai Prompt 模板 DB 存储迁移(已在 A6 裁决 P5 直接用 DB
X6 admin-portal Grafana/Jaeger iframe 嵌入 P6
X7 teacher-portal localStorage → httpOnly Cookie 迁移 P6
X8 iam JWT 密钥迁移 Vault P6
X9 api-gateway per-服务实例熔断 P6
X10 schema registry 引入events.proto 强制校验) P6+

7. 各 AI 回写义务

各 AI 收到本文档后,必须执行以下回写:

7.1 回写内容

  1. 删除自己 02-architecture-design.md 中所有"中间过渡方案"描述
  2. 对齐本文档的最终方案
  3. 更新 §8 风险与假设(移除已裁决项)

7.2 回写期限

AI 服务 回写期限 阻塞阶段
ai01 api-gateway P2 启动前
ai02 push-gateway P5 启动前
ai03 teacher-bff P2 启动前 P2
ai04 student-bff P3 启动前
ai05 parent-bff P4 启动前
ai06 iam P2 启动前 P2
ai07 classes 已是黄金模板,无需回写
ai08 core-edu P3 启动前
ai09 content P4 启动前
ai10 msg P5 启动前
ai11 data-ana P4 启动前
ai12 ai P5 启动前
ai13 teacher-portal P2 启动前 P2
ai14 student-portal P3 启动前
ai15 parent-portal P4 启动前
ai16 admin-portal P6 启动前

7.3 coord 验收

各 AI 回写完成后coord 将重新运行 §8 交叉审查,确认无"中间过渡方案"残留。


8. 变更记录

日期 变更 决策者
2026-07-09 初始创建,覆盖 G1-G17 / B1-B8 / I1-I8 / C1-C11 / N1-N5 / M1-M5 / D1-D5 / A1-A8 / P1-P6 / W1-W8 / F1-F12 共 80+ 项裁决 coord用户确认