Files
Edu/docs/architecture/004_architecture_impact_map.md
SpecialX 62682b9d61 docs(docs): 004 arch.db 二次校验 + 新增 v2 架构重设计 spec
004 修正 7 处与代码不符描述:

- proto 统计 / 包名 / core-edu gRPC service 数

- msg RPC 数 / data-ana RPC 数

- student-bff 模块数 / parent-bff 模块数

新增 v2 架构重设计 spec(996 行):

- Apollo Federation BFF 联邦

- DataScope @requires 运行时解析

- iam 拆分 config-service

- content CQRS / ai 无状态化

- SSE 优先 / Temporal 不引入

Spec 自审修复 6 处问题:

- apollo-router 端口冲突 4000→4011

- Kafka topic 命名一致性

- CDC/Outbox 投影器职责分工

- 改动点数字 / 服务数 / 容器数计算
2026-07-14 21:25:37 +08:00

1541 lines
80 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 架构影响地图(微服务版)
> 版本2.0
> 日期2026-07-14
> 状态:实施状态同步(基于代码现状 + arch.db 校准)
> 适用范围Edu 微服务架构DDD + EDA + CQRS
> 关联文档:
>
> - [理想蓝图](./0010_architecture.md)
> - [项目规则](../../.trae/rules/project_rules.md)
> - [路线图](./roadmap/README.md)
> - [端口分配唯一源](../../infra/port-allocation.md)
> - [P6 附录](./004-p6-addendum.md)
> **v2.0 变更摘要**:基于代码现状(截至 2026-07-14全面校准服务清单、模块边界、依赖关系、Kafka topic、可观测性栈、BFF 实现细节;新增 §15 实施状态索引。
>
> **arch.db 二次校验2026-07-14**:运行 `pnpm run arch:scan` 重建 arch.db22 模块 / 4715 符号 / 475 契约),据此修正 §11.1 proto 统计8 文件 / 23 service / 305 message / 139 RPC、§11.2 proto 包名(`next_edu_cloud.<domain>.v1`、§15.4 core-edu gRPC9 service / 43 RPC、§15.6 msg gRPC17 RPC、§15.7 data-ana gRPC18 RPC、§15.10 student-bff 模块8、§15.11 parent-bff 模块6
---
## 目录
1. [项目概述](#1-项目概述)
2. [技术栈](#2-技术栈)
3. [分层架构](#3-分层架构)
4. [服务依赖图](#4-服务依赖图)
5. [认证与权限](#5-认证与权限)
6. [数据访问与缓存](#6-数据访问与缓存)
7. [事件驱动架构](#7-事件驱动架构)
8. [跨服务协作](#8-跨服务协作)
9. [核心业务流程](#9-核心业务流程)
10. [可观测性](#10-可观测性)
11. [契约与 API 架构](#11-契约与-api-架构)
12. [架构约束](#12-架构约束)
13. [ADR 记录](#13-adr-记录)
14. [附录6 阶段路线图](#14-附录6-阶段路线图)
15. [实施状态索引v2.0 新增)](#15-实施状态索引v20-新增)
---
## 1. 项目概述
### 1.1a 技术分层视角(系统边界)
> 本图展示**部署分层结构**(自上而下:用户 → 微前端 → 网关 → BFF → 业务服务 → 总线 → 数据)。
> 用户层按"使用场景域"标注BFF 层按场景域分(不是按角色分)。业务领域视角见 [1.1b](#11b-业务领域视角)。
> 端口标注见 [infra/port-allocation.md](../../infra/port-allocation.md)(唯一源)。
```mermaid
graph TB
subgraph Users["用户层(场景域用户)"]
Teacher["教学场景域用户<br/>(教师 / 教导主任 / 教研组长 共用)"]
Student["学习场景域用户<br/>(学生)"]
Parent["家长场景域用户<br/>(家长)"]
Admin["管理场景域用户<br/>(系统管理员 / 校管理员)"]
end
subgraph MFE["微前端层Module Federation<br/>Next.js 15 + standalone"]
TeacherPortal["teacher-portal :4000<br/>Shell 宿主 + 教学场景域"]
StudentPortal["student-portal :4001<br/>Remote"]
ParentPortal["parent-portal :4002<br/>Remote被 teacher-portal 加载)"]
AdminPortal["admin-portal :4003<br/>Remote"]
end
subgraph PortalShell["Portal Shell 层(规划中)<br/>详见 [0020 Portal Shell 架构](./0020_portal_shell_architecture.md)"]
PortalShellApp["portal-shell :4010<br/>Modular Monolith + Micro-kernel<br/>取代 MF 微前端,单服务部署"]
end
subgraph Gateway["网关层Go 1.25 / Gin"]
APIGateway["api-gateway :8080<br/>JWT RS256 + JWKS + 限流 + 熔断"]
PushGateway["push-gateway :8081<br/>WebSocket + Redis Pub/Sub<br/>gRPC 豁免HTTP /internal/*"]
end
subgraph BFF["BFF 聚合层NestJS / GraphQL Yoga<br/>按使用场景域分 BFF"]
TeacherBFF["teacher-bff :3003<br/>Teacher + Admin Resolvers<br/>6 下游 gRPC 客户端"]
StudentBFF["student-bff :3009<br/>Cache + CircuitBreaker + Event"]
ParentBFF["parent-bff :3010<br/>Aggregation + Kafka 订阅"]
end
subgraph Services["业务微服务NestJS + FastAPI"]
IAM["iam :3002 / gRPC :50052<br/>5 Controller + Outbox"]
CoreEdu["core-edu :3004 / gRPC :50053<br/>10 模块(含合并的 classes"]
Content["content :3005 / gRPC :50054<br/>7 模块 + Neo4j + ES sync"]
DataAna["data-ana :3006 / gRPC :50055<br/>FastAPI + CDC consumer"]
Msg["msg :3007 / gRPC :50056<br/>4 模块 + 4 渠道 + Kafka 16 事件"]
AI["ai :3008 / gRPC :50058<br/>FastAPI + LLM Failover + Workflow"]
end
subgraph Bus["事件总线"]
Kafka[("Kafka<br/>双 listener 29092/9092")]
Debezium["Debezium Connect 2.7<br/>CDC MySQL → Kafka"]
end
subgraph Data["数据层"]
MySQL[("MySQL 8.0<br/>每服务独占 schema")]
Redis[("Redis 7<br/>缓存/会话/Pub/Sub")]
ClickHouse[("ClickHouse 24.3<br/>读模型宽表")]
Neo4j[("Neo4j 5.20<br/>知识图谱")]
ES[("Elasticsearch 8.13<br/>题库检索")]
end
Teacher --> TeacherPortal
Student --> StudentPortal
Parent --> ParentPortal
Admin --> AdminPortal
TeacherPortal --> APIGateway
StudentPortal --> APIGateway
ParentPortal --> APIGateway
AdminPortal --> APIGateway
TeacherPortal -.MF Remote 加载.-> ParentPortal
TeacherPortal -.WS 推送.-> PushGateway
StudentPortal -.WS 推送.-> PushGateway
ParentPortal -.WS 推送.-> PushGateway
APIGateway --> TeacherBFF
APIGateway --> StudentBFF
APIGateway --> ParentBFF
APIGateway -.admin graphql 透传.-> TeacherBFF
PushGateway -.HTTP /internal/push.-> Msg
TeacherBFF --> IAM
TeacherBFF --> CoreEdu
TeacherBFF --> Content
TeacherBFF --> DataAna
TeacherBFF --> AI
TeacherBFF --> Msg
StudentBFF --> IAM
StudentBFF --> CoreEdu
StudentBFF --> DataAna
ParentBFF --> IAM
ParentBFF --> CoreEdu
ParentBFF --> DataAna
ParentBFF --> Msg
ParentBFF -.HTTP.-> PushGateway
CoreEdu <--> Kafka
Content <--> Kafka
DataAna <--> Kafka
Msg <--> Kafka
IAM <--> Kafka
AI <--> Kafka
MySQL --> Debezium
Debezium --> Kafka
IAM --> MySQL
CoreEdu --> MySQL
Content --> MySQL
Msg --> MySQL
Content --> Neo4j
Content --> ES
DataAna --> ClickHouse
AI --> ES
IAM --> Redis
CoreEdu --> Redis
TeacherBFF --> Redis
StudentBFF --> Redis
ParentBFF --> Redis
DataAna --> Redis
AI --> Redis
PushGateway --> Redis
```
### 1.1b 业务领域视角
> 本图按 **DDD 限界上下文**展示 6 个业务领域及其依赖关系。同一服务可横跨多个领域(如 core-edu 同时承载"教学组织"与"教学核心")。
> 技术分层视角见 [1.1a](#11a-技术分层视角系统边界)。
```mermaid
graph TB
subgraph D1["D1 身份认证领域iam 服务)"]
IAM[iam 服务]
IAM_M["5 Controller: Iam / Rbac / Audit / Jwks / IamGrpc<br/>users / roles / permissions / refresh_tokens / sessions<br/>totp / audit_logs / navigation_config / route_permission"]
end
subgraph D2["D2 教学组织领域core-edu 服务)"]
ORG["core-edu 服务<br/>classes + scheduling + leave-requests"]
ORG_M["classes / teacher-associations / subjects<br/>schedule / leave-requests"]
end
subgraph D3["D3 教学核心领域core-edu 服务)"]
TEACH["core-edu 服务<br/>exams + homework + grades + attendance"]
TEACH_M["exams / exam-extensions / homework / grades<br/>attendance / dashboard / admin / iam-consumer<br/>(含 state machine + datascope-injector"]
end
subgraph D4["D4 内容资源领域content 服务)"]
CONTENT["content 服务"]
CONTENT_M["7 模块: textbooks / chapters / knowledge-points<br/>questions / electives / lesson-plans / course-plans<br/>Neo4j 知识图谱 + ES 题库检索 + sync worker"]
end
subgraph D5["D5 沟通通知领域msg 服务)"]
MSG["msg 服务"]
MSG_M["4 模块: notifications / preferences / templates / announcements<br/>4 渠道: email / sms / push / in-app<br/>Kafka 消费 16 类事件 + Idempotency Guard"]
end
subgraph D6["D6 智能洞察领域data-ana + ai 服务)"]
DATA["data-ana 服务"]
AI["ai 服务"]
DATA_M["FastAPI HTTP /analytics + gRPC 50055<br/>CDC consumer + ClickHouse 宽表<br/>analytics / dashboard / diagnostic / warnings / mastery"]
AI_M["FastAPI HTTP /v1/ai + gRPC 50058<br/>LLM FailoverChain + Prompt Service + Quality Gate<br/>chat / question / expression / lesson-plan / report"]
end
IAM --> ORG
IAM --> TEACH
IAM --> CONTENT
IAM --> MSG
ORG --> TEACH
TEACH --> CONTENT
TEACH --> MSG
CONTENT --> DATA
TEACH --> DATA
AI -.gRPC.-> CONTENT
AI -.gRPC.-> DATA
AI -.gRPC.-> IAM
```
**双图并存说明**
- **1.1a 技术分层**:描述部署、流量路径、网络边界,关注"如何部署与调用"
- **1.1b 业务领域**:描述 DDD 限界上下文、聚合根、领域依赖,关注"业务边界与归属"
- 两图互补,分别服务于运维/SRE 与产品/架构视角
### 1.2 服务清单
> 端口、阶段、实施状态基于代码现状2026-07-14。✅ = 已落地,🚧 = 部分落地,⏳ = 规划中。
| 类别 | 服务名 | 语言/框架 | HTTP 端口 | gRPC 端口 | 限界上下文 | 业务领域 | 阶段 | 状态 |
| -------- | -------------- | -------------------------- | --------- | --------- | -------------------------------------------------------------------------- | ----------------------------- | ---- | ---- |
| 基础设施 | api-gateway | Go 1.25 (Gin) | 8080 | — | 网关(路由+鉴权+限流+熔断+CORS | — | P1 | ✅ |
| 基础设施 | push-gateway | Go 1.25 (Gin) | 8081 | — | 推送WS + Redis Pub/Sub + Kafka 消费) | — | P5 | ✅ |
| BFF | teacher-bff | TS (NestJS + GraphQL Yoga) | 3003 | — | 教师聚合 + Admin 命名空间聚合 | 教学场景域 | P2 | ✅ |
| BFF | student-bff | TS (NestJS + GraphQL Yoga) | 3009 | — | 学生聚合 | 学习场景域 | P3 | ✅ |
| BFF | parent-bff | TS (NestJS + GraphQL Yoga) | 3010 | — | 家长聚合 | 家长场景域 | P4 | ✅ |
| 业务 | iam | TS (NestJS) | 3002 | 50052 | 身份认证 | **D1 身份认证** | P2 | ✅ |
| 业务 | core-edu | TS (NestJS) | 3004 | 50053 | 教学核心(含原 classes | **D2 教学组织 + D3 教学核心** | P3 | ✅ |
| 业务 | content | TS (NestJS) | 3005 | 50054 | 内容资源 | **D4 内容资源** | P4 | ✅ |
| 业务 | data-ana | Python (FastAPI) | 3006 | 50055 | 数据分析 | **D6 智能洞察** | P4 | ✅ |
| 业务 | msg | TS (NestJS) | 3007 | 50056 | 消息通知 | **D5 沟通通知** | P5 | ✅ |
| 业务 | ai | Python (FastAPI) | 3008 | 50058 | AI 网关 | **D6 智能洞察** | P5 | ✅ |
| 微前端 | teacher-portal | TS (Next.js 15) | 4000 | — | 教师端MF Shell | 教学场景域 | P2 | ✅ |
| 微前端 | student-portal | TS (Next.js 15) | 4001 | — | 学生端MF Remote | 学习场景域 | P3 | ✅ |
| 微前端 | parent-portal | TS (Next.js 15) | 4002 | — | 家长端MF Remote被 teacher-portal 加载) | 家长场景域 | P4 | ✅ |
| 微前端 | admin-portal | TS (Next.js 15) | 4003 | — | 管理端MF Remote | 管理场景域 | P6 | ✅ |
| 共享包 | shared-proto | protobuf + buf v2 | — | — | 跨语言契约8 proto 文件) | — | P1 | ✅ |
| 共享包 | shared-ts | TS | — | — | TS 共享bff / outbox | — | P1 | ✅ |
| 共享包 | shared-go | Go | — | — | Go 共享env / jwks / logger / tracer | — | P1 | ✅ |
| 共享包 | shared-py | Python | — | — | Python 共享 | — | P4 | 🚧 |
| 共享包 | contracts | TS | — | — | 跨端权限点常量 | — | P3 | 🚧 |
| 共享包 | hooks | TS (React) | — | — | React Hooksauth / permission / viewports / graphql / trace / a11y | — | P2 | ✅ |
| 共享包 | ui-components | TS (shadcn 风格) | — | — | UI 组件库data-table / form / modal / chart / filter-bar / status-badge | — | P2 | ✅ |
| 共享包 | ui-tokens | TS + CSS | — | — | 设计令牌primitive / semantic-light/dark / tailwind-theme | — | P2 | ✅ |
> **历史服务**classes端口 3001已合并入 core-eduC1 裁决),目录保留作历史参考,不再构建部署。
### 1.3 CICD → Edu 模块映射
| CICD 模块(旧) | Edu 服务(新) | 迁移阶段 |
| ----------------------------------------- | -------------- | -------- |
| auth + users + rbac | iam | P2 |
| classes + subjects + enrollment | core-edu | P3 |
| courses + lessons + schedule + attendance | core-edu | P3 |
| assignments + grades + exams | core-edu | P3 |
| textbooks + knowledge-points | content | P4 |
| questions + grading | content | P4 |
| messaging + notifications | msg | P5 |
| analytics + dashboard + diagnostic | data-ana | P4 |
| ai + lesson-preparation | ai | P5 |
| search | content (ES) | P4 |
---
## 2. 技术栈
### 2.1 多语言技术栈矩阵
| 层级 | 语言 | 框架/版本 | 用途 |
| -------- | --------------- | ------------------------------------------------------- | -------------------------------------- |
| 网关层 | Go 1.25 | Gin + otelgin + prometheus | api-gateway、push-gateway |
| 业务服务 | TypeScript 5.6+ | NestJS 10 + Drizzle ORM | iam、core-edu、content、msg |
| 分析/AI | Python 3.12 | FastAPI + structlog + prometheus-client | data-ana、ai |
| BFF | TypeScript 5.6+ | NestJS 10 + GraphQL Yoga + DataLoader + opossum熔断 | teacher-bff / student-bff / parent-bff |
| 微前端 | TypeScript 5.6+ | Next.js 15 + Module Federation + Tailwind + shadcn 风格 | 4 端门户 |
| 契约 | protobuf | buf v2FILE 级 breaking | 跨语言契约定义与生成 |
| 包管理 | — | pnpm 11 / go.work / uv workspace | 多语言 monorepo |
### 2.2 多存储矩阵
| 存储 | 版本 | 用途 | 使用服务 |
| ------------- | -------- | --------------------------------------- | ------------------------------------------------------------------------------- |
| MySQL | 8.0 | 写模型主库(每服务独占 schema | iam、core-edu、content、msg |
| Redis | 7-alpine | 缓存、会话、限流计数、分布式锁、Pub/Sub | iam、core-edu、teacher-bff、student-bff、parent-bff、data-ana、ai、push-gateway |
| ClickHouse | 24.3 | 读模型宽表、分析聚合 | data-ana |
| Neo4j | 5.20 | 知识图谱、前置依赖 | content |
| Elasticsearch | 8.13 | 题库全文检索、消息全文检索 | content、msg |
### 2.3 基础设施矩阵
| 组件 | 版本 | 用途 |
| ---------------- | ---------------- | -------------------------------------------- |
| Kafka | cp-kafka 7.6 | 事件总线,领域事件异步通信(双 listener |
| Zookeeper | cp-zookeeper 7.6 | Kafka 协调 |
| Debezium Connect | 2.7 | CDCMySQL Binlog → Kafka 实时同步 |
| OpenTelemetry | SDK + OTLP | 分布式追踪HTTP / gRPC 自动埋点) |
| Jaeger | all-in-one 1.57 | 分布式 Trace 存储 + UIOTLP 4317/4318 |
| Loki | 3.2.1 | 日志聚合 |
| Promtail | 3.2.1 | 日志采集 |
| Prometheus | v2.51.0 | 指标采集(--web.enable-lifecycle15d 保留) |
| Alertmanager | v0.27.0 | 告警路由与抑制 |
| Grafana | 10.4.0 | 可观测性可视化 |
| node-exporter | v1.8.2 | 主机指标 |
| mysqld-exporter | v0.15.1 | MySQL 指标(命令行参数模式) |
| redis-exporter | v1.67.0 | Redis 指标 |
| Temporal | ⏳ 规划中 | 工作流编排考试生命周期、AI 编排) |
| Vault | ⏳ P6 | 密钥管理 |
> **v2.0 修正**Trace 存储实际使用 **Jaeger all-in-one**OTLP 接收),原 v1.0 文档误写为 Tempo。当前未引入 Temporal长流程编排暂由 ai 服务内 WorkflowStateStoreRedis实现备课工作流。
---
## 3. 分层架构
### 3.1 六层架构
```mermaid
graph TB
subgraph L1["L1 客户端层"]
Browser[浏览器]
Mobile[移动端]
end
subgraph L2["L2 微前端层"]
MFE[Module Federation<br/>4 端门户 Next.js 15]
end
subgraph L3["L3 网关层Go 1.25 / Gin"]
GW[API Gateway :8080<br/>HTTP 反向代理 + JWT RS256 + 限流 + 熔断]
Push[Push Gateway :8081<br/>WebSocket + Redis Pub/Sub + Kafka 消费]
end
subgraph L4["L4 BFF 聚合层NestJS + GraphQL Yoga"]
BFF[3 个 BFF<br/>聚合 + DataLoader + 熔断opossum]
end
subgraph L5["L5 业务微服务层"]
SVC[6 业务服务<br/>NestJS + FastAPI<br/>DDD + CQRS + Outbox]
end
subgraph L6["L6 数据与总线层"]
DB[(MySQL / ClickHouse / Neo4j / ES)]
REDIS[(Redis 7)]
KAFKA[(Kafka + Debezium CDC)]
TEMPORAL["Temporal<br/>⏳ 规划中"]
end
Browser --> MFE
Mobile --> MFE
MFE --> GW
MFE -.WS 推送.-> Push
GW -- HTTP 代理 --> BFF
GW -- HTTP 代理 --> SVC
BFF -- gRPC --> SVC
SVC --> DB
SVC --> REDIS
BFF --> REDIS
SVC <--> KAFKA
SVC -.规划中.-> TEMPORAL
Push --> REDIS
Push -.Kafka 消费.-> KAFKA
```
### 3.2 依赖方向
```
L1 客户端 → L2 微前端 → L3 网关 → L4 BFF → L5 业务服务 → L6 数据/总线
```
**严格规则**
1. L3 网关层只做路由、鉴权、限流、熔断,**不写业务逻辑**;只做 HTTP 反向代理,不做协议转换
2. L4 BFF 层只做聚合、裁剪、协议转换GraphQL → gRPC**不持有业务状态**
3. L5 业务服务之间通过 gRPC同步或 Kafka 事件(异步)通信,**不直接访问对方数据库**
4. L6 数据层每个微服务独占自身数据库,**禁止跨库联表**
---
## 4. 服务依赖图
```mermaid
graph TB
subgraph Gateway["网关层"]
APIGW[api-gateway :8080]
PushGW[push-gateway :8081]
end
subgraph BFF["BFF 层"]
TBFF[teacher-bff :3003]
SBFF[student-bff :3009]
PBFF[parent-bff :3010]
end
subgraph Services["业务服务"]
IAM[iam :3002]
CoreEdu[core-edu :3004]
Content[content :3005]
DataAna[data-ana :3006]
Msg[msg :3007]
AI[ai :3008]
end
subgraph Shared["共享包"]
Proto[shared-proto<br/>8 proto]
SharedTS[shared-ts<br/>bff/outbox]
SharedGo[shared-go<br/>env/jwks/logger/tracer]
SharedPy[shared-py]
Contracts[contracts<br/>权限点]
Hooks[hooks<br/>React Hooks]
UIComps[ui-components]
UITokens[ui-tokens]
end
%% Gateway → BFFHTTP 反向代理 + 路径重写)
APIGW -- HTTP 代理 --> TBFF
APIGW -- HTTP 代理 --> SBFF
APIGW -- HTTP 代理 --> PBFF
APIGW -. /api/admin/graphql 透传 .-> TBFF
APIGW -- HTTP 代理 --> IAM
APIGW -- HTTP 代理 --> CoreEdu
APIGW -- HTTP 代理 --> Content
APIGW -- HTTP 代理 --> Msg
APIGW -- HTTP 代理 --> AI
APIGW -- HTTP 代理 --> DataAna
PushGW -. HTTP /internal/push .-> Msg
PushGW -. Kafka edu.notify.notification.sent .-> Msg
%% BFF → 业务服务gRPC
TBFF -- gRPC --> IAM
TBFF -- gRPC --> CoreEdu
TBFF -- gRPC --> Content
TBFF -- gRPC --> DataAna
TBFF -- gRPC --> AI
TBFF -- gRPC --> Msg
SBFF -- gRPC --> IAM
SBFF -- gRPC --> CoreEdu
SBFF -- gRPC --> DataAna
SBFF -. Kafka 事件 .-> PushGW
PBFF -- gRPC --> IAM
PBFF -- gRPC --> CoreEdu
PBFF -- gRPC --> DataAna
PBFF -- gRPC --> Msg
PBFF -. HTTP .-> PushGW
PBFF -. Kafka 订阅 .-> CoreEdu
PBFF -. Kafka 订阅 .-> IAM
%% 业务服务间事件
CoreEdu -. Kafka 事件 .-> Content
CoreEdu -. Kafka 事件 .-> DataAna
CoreEdu -. Kafka 事件 .-> Msg
Content -. Kafka 事件 .-> DataAna
IAM -. Kafka 事件 .-> CoreEdu
IAM -. Kafka 事件 .-> Msg
AI -. gRPC .-> Content
AI -. gRPC .-> DataAna
AI -. gRPC .-> IAM
DataAna -. Kafka 事件 .-> CoreEdu
DataAna -. Kafka 事件 .-> Msg
%% 共享包依赖
IAM --> Proto
CoreEdu --> Proto
Content --> Proto
DataAna --> Proto
Msg --> Proto
AI --> Proto
APIGW --> SharedGo
PushGW --> SharedGo
IAM --> SharedTS
CoreEdu --> SharedTS
Content --> SharedTS
Msg --> SharedTS
TBFF --> SharedTS
SBFF --> SharedTS
PBFF --> SharedTS
```
### 4.1 服务间通信矩阵
| 调用方 → 被调用方 | 协议 | 场景 |
| ------------------------- | ---------------- | ------------------------------------------ |
| api-gateway → BFF | HTTP 反向代理 | 路由分发 + 剥离 `/api/v1/{bff}` 前缀 |
| api-gateway → 业务服务 | HTTP 反向代理 | 剥离 `/api` 前缀,保留 `/v1/{domain}/*` |
| api-gateway → teacher-bff | HTTP 透传 | `/api/admin/graphql``/graphql`admin |
| BFF → 业务服务 | gRPC | 同步查询聚合 + DataLoader 批量去重 |
| push-gateway → msg | HTTP /internal/* | msg 主动推送X-Internal-Key 鉴权) |
| push-gateway → msg | Kafka 消费 | 消费 `edu.notify.notification.sent` |
| parent-bff → push-gateway | HTTP | 触发家长端推送 |
| CoreEdu → Content | Kafka 事件 | 教学内容变更通知 |
| CoreEdu → DataAna | Kafka 事件 | 学情数据投递9 类事件) |
| CoreEdu → Msg | Kafka 事件 | 通知触发(考试/作业/成绩/考勤) |
| IAM → CoreEdu | Kafka 事件 | 用户变更同步6 类事件) |
| IAM → Msg | Kafka 事件 | 用户/角色变更通知6 类事件) |
| Content → DataAna | Kafka 事件 | 内容发布同步 |
| DataAna → CoreEdu | Kafka 事件 | 掌握度更新 → 推荐练习 |
| DataAna → Msg | Kafka 事件 | 掌握度预警触发 |
| AI → Content | gRPC | 题库查询 / 知识点查询 |
| AI → DataAna | gRPC | 学情数据查询 |
| AI → IAM | gRPC | 用户信息查询 |
| AI → Kafka | Kafka 生产 | AI 用量事件发布(`edu.ai.usage.*` |
### 4.2 BFF 下游客户端矩阵
> 所有 BFF 下游客户端统一抽象B8 裁决):每个客户端有 `gRPC` + `mock` 两个实现,未配置 gRPC target 时自动降级为 mock。
| BFF | 下游客户端gRPC :port |
| ----------- | ---------------------------------------------------------------------------------------------------- |
| teacher-bff | iam (:50052) / core-edu (:50053) / content (:50054) / data-ana (:50055) / msg (:50056) / ai (:50058) |
| student-bff | iam / core-edu / data-ana |
| parent-bff | iam / core-edu / data-ana / msg / push-gateway (HTTP) |
---
## 5. 认证与权限
### 5.1 JWT RS256 认证流程
> 实施细节api-gateway 通过 JWKS Fetchershared-go/jwks缓存 RS256 公钥校验 JWT
> 校验通过后注入 `x-user-id` / `x-user-roles` / `x-user-data-scope` / `x-request-id` 头部HTTP 反向代理到下游服务;
> 下游服务NestJS通过 `AuthMiddleware` 解析头部、`PermissionGuard`APP_GUARD做权限校验。
> DEV_MODE=true 时跳过 JWT 校验,接受 `dev-token`。
```mermaid
sequenceDiagram
participant U as 用户
participant GW as API Gateway (Go)
participant IAM as iam 服务
participant SVC as 下游服务 (NestJS / FastAPI)
rect rgb(240, 248, 255)
Note over U,IAM: 阶段 1: 登录签发
U->>GW: POST /api/v1/iam/login {username, password}
GW->>IAM: HTTP 反向代理(无鉴权路由)
IAM->>IAM: bcrypt 校验 + 查询权限 (PermissionCacheService)
IAM->>IAM: 生成 JWTRS256 私钥签发)+ refresh_token
IAM->>IAM: 写 iam_outboxUSER_EVENTS
IAM-->>GW: {accessToken, refreshToken, userInfo}
GW-->>U: 200 Set-Cookie httpOnly + ActionState 信封
end
rect rgb(240, 255, 240)
Note over U,SVC: 阶段 2: 请求鉴权
U->>GW: GET /api/v1/classes + Authorization: Bearer <token>
GW->>GW: JWKS Fetcher 取 RS256 公钥
GW->>GW: 校验签名 + exp/iss/aud
GW->>GW: 提取 userId/roles/dataScope
GW->>SVC: HTTP 代理 + 注入 x-user-* 头部
SVC->>SVC: AuthMiddleware 解析头部
SVC->>SVC: PermissionGuard (APP_GUARD) 校验权限
SVC->>SVC: DataScopeInjector 注入 WHERE 条件
SVC-->>GW: ActionState 响应
GW-->>U: 200 响应
end
```
### 5.2 三层角色模型
| 层级 | 来源 | 示例 | 优先级 |
| -------- | ------------- | ------------------------------- | ------ |
| 系统角色 | 系统预设 | admin、teacher、student、parent | 最高 |
| 组织角色 | 学校/班级分配 | 年级组长、班主任、学科组长 | 中 |
| 临时角色 | 临时授权 | 代课教师、临时代理 | 最低 |
**规则**:权限取三层角色权限的并集,拒绝权限取交集(任一层拒绝则拒绝)。
### 5.3 DataScope 6 级数据范围
| 级别 | 名称 | 数据范围 | 典型角色 |
| ---- | -------- | ---------- | ------------ |
| L0 | SELF | 仅本人数据 | 学生、家长 |
| L1 | CLASS | 本班数据 | 班主任、学生 |
| L2 | GRADE | 本年级数据 | 年级组长 |
| L3 | SCHOOL | 本校数据 | 校管理员 |
| L4 | DISTRICT | 本区数据 | 区教研员 |
| L5 | ALL | 全部数据 | 系统管理员 |
**实现**:业务服务在 Repository 层根据 dataScope 级别动态注入 WHERE 条件。
### 5.4 视口四层模型
视口Viewport是用户在特定场景域下的可见范围。视口既可独立配置RoleViewport 表),
也可由权限推导permission → viewport 默认映射)。新角色只需配置权限集,视口自动推导;
需要差异化时再显式配置视口。
| 层级 | 含义 | 配置载体 | 示例 |
| ------- | ---------------- | ---------------------------------- | -------------------------------------------- |
| L1 导航 | 侧边栏菜单项 | navigation_config 表 | 教导主任看到"全校成绩分析"菜单 |
| L2 路由 | 可访问路由 | route_permission 表 + Gateway 校验 | 教导主任可访问 /admin/grade-analysis |
| L3 组件 | 页面内组件可见性 | usePermission().hasPermission() | 教导主任看到"导出全校报表"按钮 |
| L4 数据 | 数据行级过滤 | DataScope 枚举 | 教导主任 DataScope=grade_managed管辖年级 |
**场景域 BFF 复用策略**
按"使用场景域"分 BFF而非按角色分。新角色复用现有 BFF通过视口差异化。
| BFF | 场景域 | 复用角色 |
| ----------- | -------- | ------------------------ |
| Teacher BFF | 教学场景 | 教师、教导主任、教研组长 |
| Student BFF | 学习场景 | 学生 |
| Parent BFF | 家长场景 | 家长 |
| Admin BFF | 管理场景 | 系统管理员、校管理员 |
**实现**:教导主任归入 Teacher BFF + 额外管理视口L1 导航增加管理菜单项L4 数据范围扩大到年级)。
**iam 服务职责**
- 认证:登录/登出/JWT/2FA
- RBAC角色/权限/角色-权限映射 CRUD
- 视口配置:导航/路由/组件级视口配置 CRUD
- DataScope数据范围解析all/grade_managed/class_taught/children/owned + 自定义)
- 权限解析 APIgetEffectivePermissions(userId) → {permissions, viewports, dataScope}
---
## 6. 数据访问与缓存
### 6.1 CQRS 读写分离
```mermaid
graph LR
subgraph Write["写路径"]
Cmd[Command 命令] --> App[Application Service]
App --> Domain[Domain 领域模型]
Domain --> Repo[Repository 写模型]
Repo --> mysql_w[(MySQL 主库)]
App --> Outbox[(Outbox 表<br/>同事务)]
end
subgraph Sync["同步链路"]
Outbox --> Relay[Relay Worker]
Relay --> kafka_sync[(Kafka)]
kafka_sync --> Proj[Projection]
Proj --> ch_sync[(ClickHouse 宽表)]
Proj --> redis_sync[(Redis 缓存)]
Proj --> es_sync[(ES 索引)]
end
subgraph Read["读路径"]
Query[Query 查询] --> ReadModel[Read Model]
ReadModel --> ch_read[(ClickHouse 宽表)]
ReadModel --> redis_read[(Redis 缓存)]
ReadModel --> es_read[(ES 索引)]
end
```
### 6.2 BFF 混合读策略
```mermaid
flowchart TD
Q[BFF 收到查询请求] --> C1{Redis 命中?}
C1 -- 是 --> R1[返回缓存]
C1 -- 否 --> C2{需要聚合多服务?}
C2 -- 否 --> C3[直接 gRPC 调用单一服务]
C3 --> C4[写入 Redis]
C4 --> R2[返回]
C2 -- 是 --> C5[并行 gRPC 调用多服务]
C5 --> C6[内存聚合裁剪]
C6 --> C7[写入 Redis 5-30s 短缓存]
C7 --> R3[返回聚合结果]
```
### 6.3 缓存策略矩阵
| 数据类型 | 存储 | TTL | 失效策略 |
| ------------- | ---------- | ------- | ------------ |
| 用户会话 | Redis | 30 分钟 | 滑动过期 |
| 权限列表 | Redis | 5 分钟 | 事件驱动失效 |
| 班级/年级列表 | Redis | 5 分钟 | 事件驱动失效 |
| 教学资源详情 | Redis | 30 秒 | 短 TTL |
| BFF 聚合结果 | Redis | 5-30 秒 | 短 TTL |
| 学情宽表 | ClickHouse | 实时 | CDC 同步 |
| 题库检索 | ES | 实时 | CDC 同步 |
---
## 7. 事件驱动架构
### 7.1 Outbox + Kafka + CDC 全链路
```mermaid
graph LR
subgraph Service["业务服务"]
Cmd[Command 处理]
Domain[Domain 聚合]
Repo[Repository]
Outbox[(Outbox 表)]
end
subgraph MySQL["MySQL 主库"]
BizTable[(业务表)]
OutboxTable[(outbox 表)]
end
subgraph Relay["Relay Worker"]
Poll[轮询 outbox<br/>每 100ms]
Publish[发布到 Kafka]
Mark[标记 processed]
end
subgraph Bus["事件总线"]
kafka_bus[(Kafka topic)]
end
subgraph Consumers["消费者"]
Proj[Projection<br/>更新读模型]
OtherSvc[其他服务<br/>业务订阅]
end
Cmd --> Domain
Domain --> Repo
Repo --> BizTable
Repo --> OutboxTable
OutboxTable --> Poll
Poll --> Publish
Publish --> kafka_bus
kafka_bus --> Proj
kafka_bus --> OtherSvc
Proj --> read_stores[(ClickHouse / Redis / ES)]
```
### 7.2 事件 Topic 分类
> 实际命名(基于 `services/*/src/shared/kafka/topic-map.ts` 与 `services/iam/src/config/kafka.ts`
> 模式 `edu.<domain>.<aggregate>.<action>`。msg 服务统一使用 `edu.notify.notification.*` 发布ARB-013
| Topic | 生产者 | 消费者 | 说明 |
| -------------------------------------- | -------- | ---------------------------- | -------------------- |
| `edu.identity.user.created` | iam | core-edu (iam-consumer)、msg | 用户创建 |
| `edu.identity.user.updated` | iam | core-edu、msg | 用户更新 |
| `edu.identity.user.deleted` | iam | msg | 用户删除 |
| `edu.identity.user.role_changed` | iam | core-edu、msg | 用户角色变更 |
| `edu.identity.role.created` | iam | msg | 角色创建 |
| `edu.identity.role.updated` | iam | msg | 角色更新 |
| `edu.teaching.exam.published` | core-edu | msg | 考试发布 |
| `edu.teaching.exam.extended` | core-edu | msg | 考试延时(实时) |
| `edu.teaching.exam.force_submitted` | core-edu | msg | 考试强制交卷(实时) |
| `edu.teaching.exam.question_reordered` | core-edu | msg | 题序打乱(实时) |
| `edu.teaching.homework.assigned` | core-edu | msg | 作业布置 |
| `edu.teaching.assignment.submitted` | core-edu | data-ana、msg | 作业提交 |
| `edu.teaching.assignment.graded` | core-edu | msg | 作业批改完成 |
| `edu.teaching.grade.recorded` | core-edu | data-ana、msg | 成绩录入 |
| `edu.teaching.attendance.recorded` | core-edu | msg | 考勤记录 |
| `edu.content.question.published` | content | ai、ES sync worker | 题目发布 |
| `edu.content.textbook.updated` | content | data-ana | 教材更新 |
| `edu.insight.mastery.updated` | data-ana | core-edu、msg | 掌握度更新 |
| `edu.notify.notification.sent` | msg | push-gateway | 通知投递(驱动推送) |
| `edu.notify.notification.read` | msg | — | 通知已读 |
| `edu.notify.notification.recalled` | msg | — | 通知撤回 |
| `edu.notify.notification.failed` | msg | — | 通知投递失败 |
| `edu.notify.notification.events` | msg | — | 兜底 topic |
| `edu.ai.usage.*` | ai | data-ana 规划中) | AI 用量事件 |
> **Outbox 表命名**:每服务独立 outbox 表iam_outbox / core_edu_outbox / content_outbox / msg_outbox由 shared-ts/outbox 模块统一管理。
> **必需依赖软失败标注**ARB-015 §17.6ISSUE-058 覆盖 ISSUE-055
>
> - push-gateway → Redis**软失败**Redis 故障仅告警 + `degraded: true` + /readyz 返 200不返 503、不触发 Pod 重启)
> - 理由Redis 故障时单实例仍能服务本地连接(仅跨实例广播失效);重启会丢失本地连接表,加剧雪崩风险
> - ISSUE-055 必需依赖列表应排除 push-gateway → Redis
### 7.3 核心领域事件
| 事件 | 触发场景 | 消费者动作 |
| --------------------- | -------------- | ------------------------------------------------ |
| UserRegistered | 新用户注册 | CoreEdu 初始化默认班级关联Msg 发送欢迎通知 |
| ExamPublished | 考试发布 | Msg 推送考试通知给学生DataAna 创建考试分析骨架 |
| HomeworkSubmitted | 学生提交作业 | DataAna 记录提交行为Msg 通知教师 |
| HomeworkGraded | 教师批改完成 | DataAna 更新掌握度Msg 通知学生 |
| MasteryUpdated | 掌握度计算完成 | CoreEdu 推荐个性化练习Msg 触发预警 |
| NotificationRequested | 通知请求 | Msg 投递通知到 4 渠道email/sms/push/in-app |
| NotificationSent | 通知投递完成 | push-gateway 通过 Kafka 消费触发 WebSocket 推送 |
---
## 8. 跨服务协作
### 8.1 同步 vs 异步决策
```mermaid
flowchart TD
Req[跨服务协作需求] --> C1{需要强一致性?}
C1 -- 是 --> C2{调用方需要立即结果?}
C2 -- 是 --> Sync[同步 gRPC 调用]
C2 -- 否 --> Saga[Saga 编排<br/>Temporal]
C1 -- 否 --> C3{需要事件最终一致?}
C3 -- 是 --> Async[异步 Kafka 事件]
C3 -- 否 --> C4{仅查询读取?}
C4 -- 是 --> Read[读模型冗余]
C4 -- 否 --> Sync
```
### 8.2 BFF 同步聚合
```mermaid
sequenceDiagram
participant U as 教师端
participant BFF as teacher-bff
participant IAM as iam
participant CoreEdu as core-edu
participant DataAna as data-ana
U->>BFF: 查询班级仪表盘
BFF->>BFF: 解析 token 获取 userId
par 并行查询
BFF->>IAM: gRPC GetUser(userId)
IAM-->>BFF: 用户信息
and
BFF->>CoreEdu: gRPC GetClassesByTeacher(userId)
CoreEdu-->>BFF: 班级列表
and
BFF->>DataAna: gRPC GetTeacherDashboardStats(userId)
DataAna-->>BFF: 统计数据
end
BFF->>BFF: 内存聚合裁剪
BFF-->>U: 仪表盘聚合数据
```
### 8.3 异步事件闭环
```mermaid
flowchart LR
A[教师录入成绩] --> B[CoreEdu 写入 MySQL + Outbox]
B --> C[Outbox Relay 发布事件]
C --> D[teaching.grade.recorded]
D --> E[DataAna 消费更新掌握度]
D --> F[Msg 消费通知学生]
E --> G[insight.mastery.updated]
G --> H[CoreEdu 消费推荐练习]
G --> I[Msg 消费掌握度预警]
```
### 8.4 Temporal 工作流编排
```mermaid
flowchart TD
Start[考试发布] --> A1[Activity: 创建考试实例]
A1 --> A2[Activity: 通知学生]
A2 --> A3[Activity: 等待作答窗口]
A3 --> A4[Activity: 收集提交]
A4 --> C1{是否全部提交?}
C1 -- 否 --> A5[Activity: 自动提交未答]
C1 -- 是 --> A6[Activity: 批改]
A5 --> A6
A6 --> A7[Activity: 发布成绩]
A7 --> A8[Activity: 生成分析]
A8 --> End[工作流完成]
```
---
## 9. 核心业务流程
### 9.1 考试生命周期
```mermaid
sequenceDiagram
participant T as 教师
participant BFF as teacher-bff
participant Core as core-edu
participant Msg as msg
participant DA as data-ana
participant S as 学生
rect rgb(240, 248, 255)
Note over T,Core: 阶段 1: 创建发布
T->>BFF: 创建考试
BFF->>Core: gRPC CreateExam
Core->>Core: 写入 MySQL + Outbox
Core-->>BFF: examId
BFF-->>T: 创建成功
Core->>Msg: ExamPublished 事件
Msg->>S: 推送考试通知
end
rect rgb(240, 255, 240)
Note over S,Core: 阶段 2: 作答提交
S->>BFF: 提交答卷
BFF->>Core: gRPC SubmitExam
Core->>Core: 写入答卷 + Outbox
Core-->>BFF: 提交成功
Core->>DA: ExamSubmitted 事件
DA->>DA: 记录提交行为
end
rect rgb(255, 240, 245)
Note over T,DA: 阶段 3: 批改出分
T->>BFF: 批改答卷
BFF->>Core: gRPC GradeExam
Core->>Core: 写入成绩 + Outbox
Core-->>BFF: 批改完成
Core->>DA: GradeRecorded 事件
DA->>DA: 更新掌握度
Core->>Msg: GradeRecorded 事件
Msg->>S: 推送成绩通知
end
```
### 9.2 高并发提交
```mermaid
flowchart TD
S[学生提交] --> GW[API Gateway]
GW --> GW1{限流检查}
GW1 -- 通过 --> BFF[BFF]
GW1 -- 拒绝 --> R1[429 限流响应]
BFF --> Core[CoreEdu]
Core --> C1{Redis 分布式锁}
C1 -- 获取锁 --> C2[写入答卷]
C2 --> C3[Outbox 事件]
C3 --> C4[释放锁]
C4 --> R2[成功]
C1 -- 锁竞争 --> C5[排队等待 500ms]
C5 --> C1
C5 --> C6{超时?}
C6 -- 是 --> R3[排队中,请稍后]
```
### 9.3 AI 辅助出题
```mermaid
sequenceDiagram
participant T as 教师
participant BFF as teacher-bff
participant AI as ai 网关
participant Content as content
participant DA as data-ana
T->>BFF: 请求 AI 出题
BFF->>AI: gRPC GenerateQuestions
AI->>Content: gRPC 查询知识点
Content-->>AI: 知识点列表
AI->>DA: gRPC 查询班级学情
DA-->>AI: 学情数据
AI->>AI: LLM 调用生成题目
AI-->>BFF: 生成的题目列表
BFF-->>T: 返回题目供教师审核
T->>BFF: 确认入库
BFF->>Content: gRPC CreateQuestions
Content-->>BFF: 入库成功
```
---
## 10. 可观测性
### 10.1 三支柱可观测性
> 实际落地Jaeger all-in-one 接收 OTLPHTTP 4318 / gRPC 4317Loki + Promtail 采集容器日志Prometheus 抓取 `/metrics` 端点。
> 所有 NestJS 服务通过 `shared/observability/{logger,metrics,tracer}.ts` 注册Go 网关通过 `shared-go/{logger,tracer}` + `otelgin`Python 服务通过 `structlog` + `opentelemetry-instrumentation-fastapi` + `prometheus-client`。
```mermaid
graph TB
subgraph App["应用层"]
NESTJS[NestJS 服务<br/>pino + prom-client + OTLP]
GO[Go 网关<br/>slog + prometheus + otelgin]
PY[Python 服务<br/>structlog + prometheus-client + OTLP]
PORTAL[Next.js portal<br/>OTel Web + Sentry]
end
subgraph Collect["采集层"]
OTEL[OpenTelemetry SDK<br/>OTLP exporter]
PROM[Prometheus 抓取<br/>/metrics]
PROMTAIL[Promtail<br/>容器日志]
end
subgraph Storage["存储层"]
LOKI[(Loki 3.2.1<br/>日志)]
JAEGER[(Jaeger 1.57<br/>TraceOTLP 4317/4318)]
PROMDB[(Prometheus v2.51<br/>指标 15d 保留)]
end
subgraph Exporters["Exporters"]
NODE[node-exporter :9100<br/>host.docker.internal]
MYSQL[mysqld-exporter :9104]
REDIS[redis-exporter :9121]
end
subgraph Vis["可视化层"]
GRAFANA[Grafana 10.4<br/>统一面板 :3030]
ALERT[Alertmanager v0.27<br/>告警路由]
end
NESTJS --> OTEL
GO --> OTEL
PY --> OTEL
PORTAL -.OTLP HTTP.-> OTEL
OTEL --> JAEGER
NESTJS --> PROM
GO --> PROM
PY --> PROM
PROM --> PROMDB
PROMTAIL --> LOKI
NODE --> PROM
MYSQL --> PROM
REDIS --> PROM
LOKI --> GRAFANA
JAEGER --> GRAFANA
PROMDB --> GRAFANA
PROMDB --> ALERT
```
### 10.2 Trace 上下文传播
```mermaid
flowchart LR
A[客户端请求] --> B[API Gateway<br/>otelgin 生成 traceId]
B --> C[BFF<br/>继承 W3C traceparent]
C --> D[业务服务 gRPC<br/>继承 metadata]
D --> E[Kafka 事件<br/>traceId 写入 header]
E --> F[消费者服务<br/>继承 traceId]
F --> G[下游存储<br/>span 记录]
G --> H[Jaeger UI<br/>查询链路]
```
**规则**
- 所有跨服务调用必须透传 W3C Trace ContextHTTP `traceparent` 头 / gRPC metadata
- Kafka 事件必须将 traceId 写入消息 header
- 日志必须包含 traceId / requestId 用于关联查询
- 关键业务操作必须创建 span创建考试、提交作业、批改、AI 生成、通知投递等)
- 每服务暴露 `/metrics`Prometheus 抓取)+ `/healthz`liveness+ `/readyz`readiness
### 10.3 健康检查与降级
| 服务类型 | /healthz 行为 | /readyz 行为 |
| ------------ | ------------- | ------------------------------------------------- |
| 网关层 | 进程存活即 ok | 检查下游可达性soft-failure |
| BFF | 进程存活即 ok | 检查 Redis + 下游 gRPC probe6 个 probe |
| 业务服务 | 进程存活即 ok | 检查 DB + Redis + Kafka + gRPC server |
| push-gateway | 进程存活即 ok | Redis 软失败(不返 503+ Kafka consumer 状态 |
| data-ana | 进程存活即 ok | ClickHouse 1s 超时 + CDC lag < 1000 + Redis + iam |
---
## 11. 契约与 API 架构
### 11.1 Protobuf 契约体系
> 实际 proto 文件位于 `packages/shared-proto/proto/`,共 8 个:`ai.proto` / `analytics.proto` / `classes.proto` / `content.proto` / `core_edu.proto` / `events.proto` / `iam.proto` / `msg.proto`。
> arch.db 统计2026-07-148 proto 文件 / 23 service / 305 message / 139 RPC。
> buf v2 配置:`lint STANDARD`(含 5 项 except 豁免)+ `breaking FILE` 级别。
> `buf.gen.yaml` 生成 6 套代码protocolbuffers {go/js/python} + grpc {go/node/python},输出到 `shared-{go,ts,py}/gen/proto/`。
```mermaid
graph TB
subgraph Proto["shared-proto/proto/ (8 文件)"]
IamProto[iam.proto<br/>IamService]
CoreEduProto[core_edu.proto<br/>9 Service: Exam/Homework/Grade/<br/>Attendance/Class/Schedule/<br/>LeaveRequest/Dashboard/Admin]
ClassesProto[classes.proto<br/>ClassService历史保留]
ContentProto[content.proto<br/>Textbook/Chapter/<br/>KnowledgeGraph/Question/<br/>Elective/LessonPlan/CoursePlan]
MsgProto[msg.proto<br/>Notification/Preference/<br/>Template Service]
DataAnaProto[analytics.proto<br/>AnalyticsService]
AiProto[ai.proto<br/>AiService]
EventsProto[events.proto<br/>领域事件 schema]
end
subgraph Gen["buf generate (buf v2)"]
BufGen[buf generate]
TSGen[shared-ts/gen/proto<br/>@bufbuild/protobuf + grpc-node]
GoGen[shared-go/gen/proto<br/>protobuf-go + grpc-go]
PyGen[shared-py/gen/proto<br/>protobuf + grpc-python]
end
subgraph Services["消费服务"]
SvcTS[NestJS 服务<br/>iam/core-edu/content/msg<br/>teacher-bff/student-bff/parent-bff]
SvcGo[Go 网关<br/>api-gateway/push-gateway]
SvcPy[Python 服务<br/>data-ana/ai]
end
IamProto --> BufGen
CoreEduProto --> BufGen
ClassesProto --> BufGen
ContentProto --> BufGen
MsgProto --> BufGen
DataAnaProto --> BufGen
AiProto --> BufGen
EventsProto --> BufGen
BufGen --> TSGen
BufGen --> GoGen
BufGen --> PyGen
TSGen --> SvcTS
GoGen --> SvcGo
PyGen --> SvcPy
```
### 11.2 契约规则
| 规则 | 说明 |
| ---------- | ------------------------------------------------------------------------------------------------------------ |
| 包命名 | proto 包名采用 `next_edu_cloud.<domain>.v1` 格式(如 `next_edu_cloud.iam.v1``next_edu_cloud.core_edu.v1` |
| Topic 命名 | Kafka topic 采用 `edu.<domain>.<aggregate>.<action>` 格式(如 `edu.identity.user.created` |
| 版本化 | 破坏性变更必须升版本v1 → v2buf breaking FILE 级别 CI 强制 |
| 字段编号 | 禁止复用已删除字段编号,使用 reserved |
| 消息命名 | PascalCase |
| 字段命名 | snake_case |
| 注释 | 每个 message 和字段必须注释 |
| CI 强制 | buf lint + buf breaking 必须通过 |
| 代码生成 | `buf generate` 生成 6 套代码go/js/python × protobuf/grpc |
### 11.3 BFF 聚合模式
```mermaid
graph LR
subgraph Client["客户端"]
Q[GraphQL 查询]
end
subgraph BFF["BFF 层"]
Resolver[GraphQL Resolver]
DataLoader[DataLoader 批量去重]
Cache[Redis 短缓存]
end
subgraph Services["业务服务"]
S1[服务 A]
S2[服务 B]
S3[服务 C]
end
Q --> Resolver
Resolver --> Cache
Cache --> DataLoader
DataLoader --> S1
DataLoader --> S2
DataLoader --> S3
```
### 11.4 错误码前缀矩阵
> 来源coord 仲裁 ARB-017 §19.6 / ARB-014 / ARB-015 / ARB-018 / G14 / F4
> 规则:服务名大写 + 下划线分隔,禁止子前缀(如 EXAMS_/HOMEWORK_/GRADES_ 已移除)
| 层级 | 服务 | 前缀 | 示例 | 仲裁依据 |
| ---- | ------------ | -------------- | ------------------------------------------------------------- | -------- |
| 网关 | api-gateway | `GW_` | GW_UNAUTHORIZED / GW_RATE_LIMITED | ARB-014 |
| 网关 | push-gateway | `PUSH_` | PUSH_DEVICE_NOT_FOUND / PUSH_CHANNEL_FAILED | ARB-015 |
| BFF | teacher-bff | `BFF_TEACHER_` | BFF_TEACHER_UNAUTHORIZED / BFF_TEACHER_BAD_GATEWAY | ARB-016 |
| BFF | student-bff | `BFF_STUDENT_` | BFF_STUDENT_UNAUTHORIZED / BFF_STUDENT_VALIDATION_ERROR | ARB-017 |
| BFF | parent-bff | `BFF_PARENT_` | BFF_PARENT_CHILD_NOT_BOUND / BFF_PARENT_BAD_GATEWAY | ARB-018 |
| 业务 | iam | `IAM_` | IAM_USER_NOT_FOUND / IAM_INVALID_CREDENTIALS | ARB-003 |
| 业务 | core-edu | `CORE_EDU_` | CORE_EDU_EXAM_NOT_FOUND / CORE_EDU_GRADE_NOT_FOUND | ARB-004 |
| 业务 | content | `CONTENT_` | CONTENT_QUESTION_NOT_FOUND / CONTENT_TEXTBOOK_NOT_FOUND | ARB-005 |
| 业务 | msg | `MSG_` | MSG_NOTIFICATION_NOT_FOUND / MSG_TEMPLATE_NOT_FOUND | ARB-008 |
| 业务 | data-ana | `DATA_ANA_` | DATA_ANA_DASHBOARD_UNAVAILABLE / DATA_ANA_ANALYTICS_NOT_READY | ARB-009 |
| 业务 | ai | `AI_` | AI_GENERATION_FAILED / AI_QUOTA_EXCEEDED | ARB-010 |
**前端 i18n key 映射规则**F4 裁决):
| 服务 | i18n key 模式 | 示例 |
| ------------ | ------------------------------- | -------------------------------------- |
| api-gateway | `error.gateway.<code_snake>` | `error.gateway.unauthorized` |
| push-gateway | `error.push.<code_snake>` | `error.push.device_not_found` |
| teacher-bff | `error.bffTeacher.<code_snake>` | `error.bffTeacher.unauthorized` |
| student-bff | `error.bffStudent.<code_snake>` | `error.bffStudent.validation_error` |
| parent-bff | `error.bffParent.<code_snake>` | `error.bffParent.child_not_bound` |
| iam | `error.iam.<code_snake>` | `error.iam.user_not_found` |
| core-edu | `error.core_edu.<code_snake>` | `error.core_edu.exam_not_found` |
| content | `error.content.<code_snake>` | `error.content.question_not_found` |
| msg | `error.msg.<code_snake>` | `error.msg.notification_not_found` |
| data-ana | `error.data_ana.<code_snake>` | `error.data_ana.dashboard_unavailable` |
| ai | `error.ai.<code_snake>` | `error.ai.generation_failed` |
### 11.5 ActionState 信封规范
> 来源coord 仲裁 ARB-017 §19.6
> 适用范围:所有 BFF / Gateway HTTP 响应、GraphQL response 的 errors 扩展字段
> 设计原则:统一错误信封 + 降级模式方案 Bdegraded 放 error.details 子字段)
**信封结构**
```typescript
interface ActionState<T = unknown> {
success: boolean; // 整体成功/失败
data: T | null; // 成功时返回数据,失败时为 null
error: {
code: string; // 错误码(见 §11.4 前缀矩阵)
message: string; // 人类可读错误消息i18n key 解析后)
details?: Record<string, unknown>; // 附加详情(含 degraded 字段)
traceId: string; // 链路追踪 IDX-Request-Id
} | null; // 成功时为 null
}
```
**降级模式(方案 B**
- `success = true`(整体成功)
- `data` 内含 `extensions.degraded: true` 子字段
- `error` 仍为 null非错误
- 用于部分聚合失败场景(如 teacher-bff 聚合 iam 成功但 core-edu 失败)
**示例 1完全成功**
```json
{
"success": true,
"data": { "userId": "u001", "name": "张老师" },
"error": null
}
```
**示例 2完全失败**
```json
{
"success": false,
"data": null,
"error": {
"code": "BFF_TEACHER_BAD_GATEWAY",
"message": "下游服务不可用",
"details": { "downstream": "core-edu", "reason": "timeout" },
"traceId": "req-abc123"
}
}
```
**示例 3降级模式部分聚合成功**
```json
{
"success": true,
"data": {
"user": { "userId": "u001", "name": "张老师" },
"classes": null,
"extensions": { "degraded": true, "failedServices": ["core-edu"] }
},
"error": null
}
```
**GraphQL errors 数组扩展**
GraphQL 响应中,错误通过 `errors[].extensions` 携带 ActionState 字段:
```json
{
"errors": [
{
"message": "下游服务不可用",
"extensions": {
"code": "BFF_TEACHER_BAD_GATEWAY",
"details": { "downstream": "core-edu" },
"traceId": "req-abc123"
}
}
]
}
```
---
## 12. 架构约束
### 12.1 服务独立性约束
| 约束 | 说明 |
| ----------- | -------------------------------------- |
| 数据库独占 | 每个微服务独占自身数据库,禁止跨库联表 |
| 契约先行 | 所有跨服务通信必须先定义 protobuf 契约 |
| Outbox 强制 | 所有领域事件必须通过 Outbox 模式发布 |
| 幂等消费 | 所有事件消费者必须实现幂等性 |
| 单一职责 | 每个服务只负责一个限界上下文 |
| 无状态服务 | 业务服务不持有会话状态Redis 承载) |
### 12.2 通信约束
| 场景 | 允许 | 禁止 |
| -------------------- | --------------------------------- | ------------------------ |
| 客户端 → Gateway | REST + WebSocket | 直连业务服务 |
| Gateway → BFF | HTTP 反向代理(路径重写剥离前缀) | gRPC 转换、REST 业务逻辑 |
| Gateway → 业务服务 | HTTP 反向代理(剥离 `/api` 前缀) | gRPC 转换 |
| BFF → 业务服务 | gRPC + DataLoader 批量去重 | 直接访问 DB |
| push-gateway → msg | HTTP /internal/* + Kafka 消费 | gRPC豁免ARB-015 |
| 业务服务之间(同步) | gRPC | REST、直接 DB |
| 业务服务之间(异步) | Kafka 事件Outbox 模式) | 直接 producer 调用 |
| 事件发布 | Outbox 模式 | 直接 Kafka producer |
### 12.3 数据一致性约束
| 场景 | 一致性级别 | 实现 |
| ------ | ---------- | --------------------- |
| 聚合内 | 强一致 | 单事务 |
| 聚合间 | 最终一致 | Kafka 事件 |
| 服务间 | 最终一致 | Kafka 事件 / Saga |
| 读模型 | 最终一致 | Projection 异步更新 |
| 缓存 | 最终一致 | 事件驱动失效 + 短 TTL |
---
## 13. ADR 记录
| 编号 | 决策 | 原因 | 状态 |
| ------- | --------------------------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------- |
| ADR-001 | 采用 DDD 限界上下文划分服务 | 业务边界清晰,独立演进 | 已采纳 |
| ADR-002 | 采用 NestJS 作为业务服务框架 | TS 生态成熟,装饰器 + DI 适合 DDD | 已采纳 |
| ADR-003 | 采用 Go 作为网关语言 | 高并发、低内存、适合网关场景 | 已采纳 |
| ADR-004 | 采用 Python 作为分析/AI 语言 | 数据科学/AI 生态丰富 | 已采纳 |
| ADR-005 | 采用 CQRS 读写分离 | 读多写少,读模型可独立优化 | 已采纳 |
| ADR-006 | 采用 Outbox 模式发布事件 | 保证事务与事件最终一致 | 已采纳 |
| ADR-007 | 采用 Kafka 作为事件总线 | 高吞吐、持久化、成熟生态 | 已采纳 |
| ADR-008 | 采用 Debezium CDC | 解耦 Outbox Relay减少业务侵入 | 已采纳 |
| ADR-009 | 采用 protobuf + buf 契约先行 | 多语言契约统一、版本化、CI 强制 | 已采纳 |
| ADR-010 | 采用 JWT RS256 非对称签名 | 网关公钥校验无需共享私钥 | 已采纳 |
| ADR-011 | 采用 DataScope 6 级数据范围 | 满足 K12 多层级数据隔离 | 已采纳 |
| ADR-012 | 采用 Module Federation 微前端 | 独立部署、技术栈无关、渐进迁移 | 已采纳 |
| ADR-013 | 采用 Temporal 工作流编排 | 长流程编排、可观测、可回滚 | ⏳ 规划中(当前由 ai 内 WorkflowStateStore 临时实现) |
| ADR-014 | 采用 ClickHouse 读模型宽表 | 分析查询亚秒级响应 | 已采纳 |
| ADR-015 | api-gateway 采用 HTTP 反向代理(非 gRPC 转换) | Go 网关只做 HTTP简化部署下游 HTTP/gRPC 双协议 | 已采纳 |
| ADR-016 | push-gateway 豁免 gRPC | 基础设施层无流式推送场景msg/student-bff/parent-bff 改用 HTTP /internal/* | 已采纳 |
| ADR-017 | classes 服务合并入 core-edu | 教学组织与教学核心共享聚合根边界 | 已采纳 |
| ADR-018 | BFF 统一 GraphQL Yoga + DataLoader + opossum 熔断 | 协议统一、批量去重、降级模式 Bdegraded 子字段) | 已采纳 |
| ADR-019 | admin-portal GraphQL 经 teacher-bff 命名空间 | 复用 teacher-bff resolveradmin role 中间件强制隔离 | 已采纳 |
| ADR-020 | parent-portal 作为 MF Remote 被 teacher-portal 加载 | 家长入口可由教师端嵌入,统一 Shell 宿主 | 已采纳 |
| ADR-021 | Trace 存储 Jaeger 替代 Tempo | all-in-one 镜像部署简单OTLP 原生支持 | 已采纳 |
| ADR-022 | 共享包 ui-tokens 替代原 shared-tokens 命名 | 三层令牌primitive/semantic/tailwind-theme实际落地 | 已采纳 |
---
## 14. 附录6 阶段路线图
### 14.1 阶段总览
```mermaid
graph LR
P1[P1 地基<br/>M1-M3] --> P2[P2 身份<br/>M4-M6]
P2 --> P3[P3 核心教学<br/>M7-M10]
P3 --> P4[P4 内容分析<br/>M11-M13]
P4 --> P5[P5 沟通AI<br/>M14-M16]
P5 --> P6[P6 硬化<br/>M17-M18]
```
### 14.2 服务与阶段映射
> 状态基于代码现状2026-07-14。✅ 已落地 / 🚧 部分落地 / ⏳ 规划中。
| 阶段 | 周期 | 交付服务 | 退出标准 | 实际状态 |
| ----------- | ------- | ----------------------------------------------------- | ------------------------------ | -------------------------------------------------------------------------------- |
| P1 地基 | M1-M3 | api-gateway、classes黄金模板、shared-proto | classes 域 CRUD 端到端跑通 | ✅ 完成classes 已合并入 core-edu |
| P2 身份 | M4-M6 | iam、teacher-bff、teacher-portal 骨架 | 教师可登录并看到空白 Dashboard | ✅ 完成 |
| P3 核心教学 | M7-M10 | core-edu合并 classes、student-bff、student-portal | 考试→作答→批改→成绩全链路 | ✅ 完成(含 LeaveRequests/Dashboard/Admin/IamConsumer 扩展) |
| P4 内容分析 | M11-M13 | content、data-ana、parent-bff、parent-portal | 知识图谱查询 + 学情宽表 5s | ✅ 完成(含 7 模块 + Neo4j + ES sync + CDC consumer + 11 analytics 端点) |
| P5 沟通AI | M14-M16 | msg、push-gateway、ai | 全校广播 + AI 辅助出题 | ✅ 完成msg 4 模块 4 渠道 + push-gateway WS + Kafka + ai 11 端点 + 备课工作流) |
| P6 硬化 | M17-M18 | admin-portal、Service Mesh | 99.9% 可用性 + 独立扩缩容 | 🚧 admin-portal 已落地Service Mesh / Vault / 99.9% SLO 待硬化 |
> 详细规划见 [路线图目录](./roadmap/README.md)、[tech-debt](./roadmap/tech-debt.md)、[pending-features](./roadmap/pending-features.md)
---
## 15. 实施状态索引v2.0 新增)
> 本节按服务/包罗列实际落地的模块、Controller、关键组件作为代码现状的快速索引。
> 详细模块设计见各服务 `README.md` 与 `docs/01-understanding.md`。
### 15.1 api-gatewayGo :8080
- **中间件链**Recovery → otelgin → RequestID → CORS → SecurityHeaders → RequestBodyLimit(10MB) → RateLimit(100rps+20burst) → CircuitBreaker → AuthMiddleware(JWKS RS256) → Metrics
- **路由组**
- `/healthz``/readyz``/metrics`(公开)
- `/api/v1/{classes,iam,exams,homework,grades,textbooks,chapters,knowledge-points,questions,notifications,messages,announcements,ai,analytics,dashboard}/*` → HTTP 反向代理
- `/api/v1/{teacher,student,parent}/*` → BFF 反向代理(剥离 `/api/v1/{bff}` 前缀)
- `/api/admin/graphql` → teacher-bff `/graphql`AdminRoleMiddleware 强制)
- **关键依赖**`shared-go/jwks`(公钥缓存)、`shared-go/env``shared-go/logger``shared-go/tracer`
### 15.2 push-gatewayGo :8081
- **WebSocket 端点**`/ws`JWT RS256 via query `?token=` 或 Authorization 头)
- **内部 HTTP API**`/internal/push``/internal/broadcast``/internal/online/:userID`X-Internal-Key 鉴权)
- **跨实例广播**Redis Pub/SubSubscribeAll + RebuildPresenceOnStartup
- **Kafka 消费**`edu.notify.notification.sent`ARB-013
- **健康检查**`/healthz`liveness`/readyz`Redis 软失败 + Kafka consumer 状态)
- **依赖**`hub`in-memory connection registry`redisclient``kafkaconsumer``ws``observability`
### 15.3 iamNestJS :3002 / gRPC :50052
- **Controllers**IamController、RbacController、AuditController、JwksController、IamGrpcController
- **Services**IamService、JwksService、PermissionCacheServiceRedis、TokenBlacklistService
- **Outbox**`iam_outbox` 表,发布到 `edu.identity.user.*` topic
- **APP_GUARD**PermissionGuardDB 驱动 + Redis 缓存I3 裁决)
- **AuthMiddleware** 应用范围:`v1/iam/me``logout``change-password``viewports``permissions/effective``children``roles``permissions``users``audit``totp`
### 15.4 core-eduNestJS :3004 / gRPC :50053
- **业务模块10**
- exams含 exam-extensions、exam-state-machine
- homework含 homework-state-machine
- grades含 grade-calculator
- attendance
- classes含 teacher-associationsC1 合并自原 classes 服务)
- scheduling含 schedule-conflict 检测)
- leave-requestsP3.13
- dashboard
- admin
- iam-consumer消费 IAM 6 类事件)
- **共享组件**datascope-injectorRepository 层 WHERE 注入、outboxcore_edu_outbox、global-error.filter
- **gRPC 服务943 RPC**ExamService / HomeworkService / GradeService / AttendanceService / ClassService / ScheduleService / LeaveRequestService / DashboardService / AdminService
### 15.5 contentNestJS :3005 / gRPC :50054
- **业务模块7**textbooks、chapters、knowledge-points、questions、electives、lesson-plans、course-plans
- **gRPC controllers7**Textbook / Chapter / KnowledgeGraph / Question / Elective / LessonPlan / CoursePlan
- **同步 worker**es-sync.worker题库 ES 索引、neo4j-sync.worker知识图谱节点
- **Outbox**content_outbox发布 `edu.content.*` 事件
- **存储**MySQL业务表+ Neo4j知识图谱+ Elasticsearch题库检索
### 15.6 msgNestJS :3007 / gRPC :50056
- **业务模块4**notifications、preferences、templates、announcements
- **gRPC controllers317 RPC**NotificationService9 RPC/ NotificationPreferenceService2 RPC/ NotificationTemplateService6 RPCARB-008 裁剪)
- **渠道4**email、sms、push、in-appchannel-dispatcher 路由)
- **Kafka 消费**16 类事件iam 6 + core-edu 9 + data-ana 1`shared/kafka/topic-map.ts`
- **Kafka 生产**4 类 `edu.notify.notification.*` 事件 + 1 兜底 topic
- **辅助组件**push-gateway.clientHTTP 调用 /internal/push、idempotency.guardRedis SETNX 去重、Outboxmsg_outbox
- **存储**MySQL + Elasticsearch消息全文检索+ Redis幂等性
### 15.7 data-anaFastAPI :3006 / gRPC :50055
- **HTTP 端点3 基础 + 11 业务 = 14**
- 基础:`/``/healthz``/readyz`
- 业务(全部 ActionState 信封):
- `/analytics/class/{class_id}/performance`
- `/analytics/student/{student_id}/{weakness,trend,errorbook,mastery}`
- `/analytics/{teacher,student,parent,admin}/dashboard`
- `/analytics/warnings` + `/analytics/warnings/trigger`
- `/analytics/class/{class_id}/mastery-distribution`
- **gRPC 服务**AnalyticsService18 RPC
- **CDC 消费者**:手动 commitlag 阈值 1000超过 readyz 返 503
- **/readyz 4 依赖**ClickHouse1s+ CDC consumerlag<1000+ Redis200ms+ iam gRPC2s
- **存储**ClickHouse宽表+ Redis缓存+ iam gRPC用户信息
### 15.8 aiFastAPI :3008 / gRPC :50058
- **HTTP 端点11**
- `/healthz``/readyz`
- `/v1/ai/chat`(非流式)+ `/v1/ai/chat/stream`SSE
- `/v1/ai/generate/question` + `/v1/ai/generate/question/stream`SSE
- `/v1/ai/optimize/expression`
- `/v1/ai/lesson-plan/generate` + `/v1/ai/lesson-plan/status/{workflow_id}` + `/v1/ai/lesson-plan/confirm/{workflow_id}`
- `/v1/ai/generate/report`class_summary / student_detail / exam_analysis
- **gRPC 服务**AiService9 RPC
- **核心组件**LLM FailoverChain4 适配器 + 熔断 + 故障切换、PromptTemplateServiceJinja2 + YAML、QualityGateRuleValidator + LLMJudge
- **用量与配额**UsageRecorderRedis+ QuotaEnforcer + KafkaProducer`edu.ai.usage.*`
- **限流**RateLimiterRedis 三维度令牌桶user/ip/school
- **安全**PII redactor + 输入清洗 + 输出审核
- **备课工作流**4 步编排 + WorkflowStateStoreRedis TTL
- **下游 gRPC 客户端**ContentClientGrpc / DataAnaClientGrpc / IamClientGrpc连接失败降级不阻断启动
### 15.9 teacher-bffNestJS :3003 / GraphQL Yoga
- **模块**GraphQLModuleTeacher + Admin ResolversARB-001 扁平合并)+ HealthModule + MiddlewareModule
- **下游客户端6**iam / core-edu / content / data-ana / msg / aiB8 裁决统一抽象gRPC + mock 双实现)
- **GraphQL 端点**`/graphql`(同时承载 teacher 与 admin 命名空间)
- **SSE 控制器**`ai-chat-sse.controller.ts`(透传 ai 服务流式响应)
- **Health probes6**iam-grpc / core-edu-grpc / content-grpc / data-ana-grpc / ai-grpc / msg-grpc + redis probe
### 15.10 student-bffNestJS :3009 / GraphQL Yoga
- **模块8**CacheModuleGlobal Redis+ DownstreamModuleGlobal gRPC+ CircuitBreakerModuleGlobal opossum+ HealthModule + DataLoaderModule + StudentModuleGraphQL Yoga + Resolver+ PushGatewayModuleHTTP /internal/push+ EventModuleKafka 事件订阅 + push-gateway 推送)
- **下游客户端**iam / core-edu / data-ana
### 15.11 parent-bffNestJS :3010 / GraphQL Yoga
- **模块6**HealthModule + GraphqlModuleYoga /v1/graphql+ ClientsModuleiam + core-edu + data-ana + msg + push-http+ KafkaModulecache-invalidation + notification-push handler+ AggregationModuleorchestrator + fallback-strategy + child-guard + response-mapper+ DataLoaderModuledataloader.factory + loaders 批量去重)
- **缓存**Redis + LRU cache + cache-key.builder
### 15.12 teacher-portalNext.js 15 :4000MF Shell
- **路由组**25+ 业务页面dashboard、classes、schedule、exams、homework、grades、attendance、analytics、knowledge-graph、lesson-plans、course-plans、textbooks、questions、notifications、students、ai-assist、ai-lesson-plan、ai-report、diagnostic、error-book、practice、leave、elective、schedule-changes、settings
- **MF Remote 加载**ParentPortalRemote在 teacher-portal 内嵌入家长端视图)
- **GraphQL 客户端文件**graphql.tsbase+ graphql-p4.ts / p5.ts / p7-admin.ts / p7-advanced.ts / p7-exams.ts / p7-grades.ts / p7-insights.ts按阶段渐进扩展
- **可观测性**observability-providerOTel Web + Sentry + web-vitals + performance-dashboard
- **国际化**messages/{en,zh-CN}.json
- **认证**lib/auth.tscookie 迁移 + token 刷新 + cross-tab sync
### 15.13 student-portal / parent-portal / admin-portalNext.js 15 :4001/:4002/:4003MF Remote
- **student-portal**:路由组 leave + 主页exam-types 类型mocks/handlers + server
- **parent-portal**login + 主页 + providerschild-storeZustandmiddleware.tsPWAmanifest + sw.js
- **admin-portal**login + admin layouthooksuse-classes/files/roles/school/students/teachers/users/graphqllib/{auth,i18n,permissions,web-vitals}
### 15.14 共享包实施状态
| 包 | 关键导出 | 状态 |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---- |
| shared-proto | 8 proto 文件 + buf.yaml + buf.gen.yaml生成 6 套代码) | ✅ |
| shared-ts | `bff/`logger`outbox/`OutboxModule + publisher + schema + types被 iam/core-edu/content/msg/BFF 共享) | ✅ |
| shared-go | `env/`config.Load`jwks/`FetcherRS256 公钥缓存)、`logger/`slog JSON`tracer/`OTLP init | ✅ |
| shared-py | pyproject.tomluv workspace member | 🚧 |
| contracts | `STUDENT_PERMISSIONS` 常量12 权限点) | 🚧 |
| hooks | use-auth / use-permission / use-viewports / use-graphql-client / use-trace-id / use-a11y-id / use-aria-live / use-api / use-toast | ✅ |
| ui-components | data-table / filter-bar / form / modal / chart / calendar / status-badge / empty / loading + utils/cn | ✅ |
| ui-tokens | primitive.css / semantic-light.css / semantic-dark.css / tailwind-theme.css / all.css + colors/shadows/spacing/typography (.ts) | ✅ |
### 15.15 部署与运维实施状态
- **本地开发**`infra/docker-compose.yml`(基础设施)+ pnpm dev / go run / uv run
- **最小化部署**`infra/docker-compose.minimal.yml`
- **生产部署**`infra/docker-compose.deploy.yml`build: 替代 image:
- **测试部署**`infra/docker-compose.test.yml`
- **监控栈**`infra/docker-compose.monitoring.yml`observability profile
- **K8s Helm chart**`infra/k8s/helm/`edu-platform umbrella + 各子 chart
- **CI/CD**`.github/workflows/ci.yml`quality-ts / quality-go / quality-proto / deployno-push 本地构建模式)
- **备份**`infra/backup/backup-mysql.sh`(每服务独立,保留 7 天)
- **混沌工程**`infra/chaos/experiments.yaml`
- **WAF**`infra/security/waf-rules.conf`
- **端口分配**`infra/port-allocation.md`(唯一源)
### 15.16 文档体系实施状态
| 路径 | 用途 |
| -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `docs/architecture/004_architecture_impact_map.md` | 本文件(架构影响地图,设计意图唯一源) |
| `docs/architecture/0010_architecture.md` | 理想蓝图(目标态) |
| `docs/architecture/004-p6-addendum.md` | P6 硬化附录 |
| `docs/architecture/roadmap/` | tech-debt / pending-features / integration-test-phase |
| `docs/architecture/runbooks/` | p6-hardening / post-p6-followup / incident-response |
| `docs/architecture/issues/` | 协调记录coord / matrix / workline+ contracts/ + objections/ + worklines/ |
| `docs/architecture/ai-allocation.md` | AI 模块分配 |
| `docs/architecture/ai-work-orchestration.md` | AI 工作编排 |
| `docs/architecture/coord-cross-review.md` | coord 交叉审查 |
| `docs/architecture/coord-final-decisions.md` | coord 最终裁决ARB-001~022+ |
| `docs/architecture/president-final-rulings.md` | president 最终裁决batch 0.9+ |
| `docs/modules/<service>/README.md` | 各服务模块文档iam/core-edu/content/msg/data-ana/ai/api-gateway/push-gateway/classes |
| `docs/standards/` | coding-standards / cicd-runbook / full-stack-runbook / git-workflow / local-dev-runbook / multi-ai-collaboration / ui-design-system |
| `docs/troubleshooting/known-issues.md` | 已知问题速查(索引式场景→技术映射) |
---
> **本文件 v2.0 已基于代码现状2026-07-14全面校准。后续代码变更须按 [项目规则 §1](../../.trae/rules/project_rules.md) 同步更新本文件 + 运行 `pnpm run arch:scan`。**