Commit Graph

205 Commits

Author SHA1 Message Date
SpecialX
514e26ebb4 feat(portal-shell): implement portal-shell with apollo-router integration
M8: portal-shell unified frontend shell (Modular Monolith + micro-kernel).

- Apollo Client -> apollo-router (port 4010, RSC prefetch)

- 5 layouts: classic/focus/split/triple/canvas

- Registry + PluginLoader (dynamic import ssr:false)

- 3-layer props merge, Zustand PluginStore

- 4 widgets: grades/notification-bell/user-menu/class-selector

- config-service: new pluginConfig GraphQL resolver

- apollo-router: CORS + header propagation for portal-shell

- docker-compose.yml: portal-shell service block
2026-07-15 08:06:09 +08:00
SpecialX
47e950c664 feat(ai): temporal worker for lesson plan workflow
- deploy temporal server (postgresql + auto-setup + ui) in docker-compose
- new temporal/ module: workflow + activities + worker manager
- convert lesson plan 4-step orchestration to temporal workflow
- activities wrap existing analyze/recommend/generate/prepare_review steps
- worker injects failover_chain/content_client/data_ana_client via module globals
- start() uses temporal client.start_workflow, falls back to asyncio in dev
- register temporal ports 7233/8085 in port-allocation

Implements M6.5 of v2.1 migration plan (ADR-030).
2026-07-15 02:34:34 +08:00
SpecialX
ce5aeec955 refactor(ai): stateless workflow store with redis-only mode
- remove in-memory fallback (ADR-028: ai must be stateless)
- Redis is the only state store, shared across instances
- Redis unavailable raises RedisError instead of degrading to memory
- key prefix workflow -> ai:workflow (spec 4.3)
- TTL 24h -> 1h (spec 4.3: long-lived state managed by Temporal)

Implements M6 of v2.1 migration plan.
2026-07-15 02:22:28 +08:00
SpecialX
1423a0b8eb feat(core-edu): dataspcope @requires with scopetoken resolution
- new DataScopeResolver extends iam UserDataScope via @extends
- visibleGrades @requires(studentScopeToken) + visibleExams @requires(classScopeToken)
- resolve ScopeToken via Redis sMembers to actual ID list (ADR-041)
- add findByStudentIds/findByClassIds/findAll to repositories
- ALL token = full visibility (admin), skip WHERE IN filter

Implements M4 of v2.1 migration plan.
2026-07-15 02:20:15 +08:00
SpecialX
1a5fa78fa6 feat(config-service): split config-service from iam for plugin/layout config
- new NestJS service on port 3011/gRPC 50059 (ADR-026)
- owns 6 config_ tables (plugin/role-mapping/role-layout/layout-tpl/user-override/outbox)
- GraphQL Federation 2 subgraph with DataLoader + RouterAuthGuard
- gRPC ConfigService + admin REST CRUD + user REST API
- three-layer merge: registry.defaultProps + roleMapping.widget_props + userOverride.props
- Redis cache with 5min TTL
- registered in apollo-router supergraph + docker-compose + port-allocation

Implements M3 of v2.1 migration plan.
2026-07-15 02:13:03 +08:00
SpecialX
163bff6666 feat(infra): apollo router deployment and supergraph composition
M2: Apollo Router replaces BFF manual aggregation (ADR-037)

- Dockerfile: self-contained with rover + router, auto-compose on startup

- router.yaml: CORS, Router-Authorization header injection, traffic shaping

- supergraph.yaml: 6 subgraphs (iam/core-edu/content/msg/ai/data-ana)

- docker-compose: apollo-router on port 3000, depends on all subgraphs

- ROUTER_AUTH_SECRET added to secrets.example.env

- port-allocation.md: apollo-router registered on port 3000
2026-07-15 01:32:14 +08:00
SpecialX
6af1aa0d82 feat(push-gateway,msg): redis pubsub backplane for real-time notifications
M7: ADR-040 Redis Pub/Sub as state routing backplane

- push-gateway: remove Kafka consumer, add SSE endpoint

- SSE: subscribe to Redis user:{userId}:notify on connect

- msg: publish notifications to Redis Pub/Sub instead of HTTP push

- docker-compose: remove Kafka env from push-gateway
2026-07-15 01:28:55 +08:00
SpecialX
a75527be80 feat(content): eager invalidation and optimistic lock for cqrs
M4: ADR-038 Eager Invalidation + ADR-039 Optimistic Lock

- EagerInvalidationService: Redis DEL after MySQL commit

- Cache key conventions for textbook/chapter/kp/question

- Version header check (If-Match/X-Expected-Version) on write endpoints

- 409 Conflict on version mismatch

- All write endpoints return updatedAt timestamp
2026-07-15 01:28:20 +08:00
SpecialX
47a062606f refactor(shared-ts,iam,core-edu,content,msg): remove outbox polling publisher
M8: Debezium CDC now handles outbox table to Kafka (ADR-032)

- Remove OutboxPublisher class from shared-ts

- Remove publisher from iam/core-edu/content/msg lifecycle and modules

- OutboxService retained for transactional outbox table writes

- Debezium monitors binlog and pushes to Kafka automatically
2026-07-15 01:27:45 +08:00
SpecialX
a3f4fd013e feat(data-ana): python graphql federation subgraph with strawberry
- strawberry-graphql[asgi] dependency added

- 13 Federation 2 types: ClassPerformance/StudentWeakness/Dashboards/Mastery/ErrorBook

- 11 Query resolvers delegate to existing analytics/mastery services

- RouterAuthMiddleware validates Router-Authorization header on /graphql

- GraphQL endpoint mounted at /graphql alongside existing REST endpoints
2026-07-15 00:57:02 +08:00
SpecialX
1dcdcf23fd feat(ai): python graphql federation subgraph with strawberry
- strawberry-graphql[asgi] dependency added

- GeneratedReport and LessonPlanStatus @key types with resolve_reference

- RouterAuthMiddleware validates Router-Authorization header on /graphql

- GraphQL endpoint mounted at /graphql in FastAPI app

- WorkflowStateStore injected for lesson plan status resolution
2026-07-15 00:56:37 +08:00
SpecialX
35aa56537d chore(ai): add proto-generated graphql schema reference
Python service needs strawberry-graphql federation implementation
2026-07-15 00:20:21 +08:00
SpecialX
d3b126ed9d feat(msg): graphql subgraph with dataloader for notification/template
- GraphQLModule: Apollo Federation 2 at /graphql

- Notification/NotificationTemplate @key with @ResolveReference

- RouterAuthGuard: validate Router-Authorization header (ADR-036)

- batchFindByIds added to notifications and templates repositories
2026-07-15 00:19:26 +08:00
SpecialX
d59c4e585f feat(content): graphql subgraph with dataloader for textbook/chapter/kp/question
- GraphQLModule: Apollo Federation 2 at /graphql

- Textbook/Chapter/KnowledgePoint/Question @key with @ResolveReference

- RouterAuthGuard: validate Router-Authorization header (ADR-036)

- batchFind methods added to 4 repositories

- Domain modules export repositories for GraphqlModule injection
2026-07-15 00:18:57 +08:00
SpecialX
9ff7a61ee2 feat(core-edu): graphql subgraph with dataloader for exam/homework/grade/class
- GraphQLModule: Apollo Federation 2 at /graphql

- Exam/Homework/Grade/ClassInfo @key with @ResolveReference using DataLoader

- RouterAuthGuard: validate Router-Authorization header (ADR-036)

- batchFind methods added to exams/homework/grades/classes repositories

- Domain modules export repositories for GraphqlModule injection
2026-07-15 00:18:30 +08:00
SpecialX
6bed673d9f feat(iam): graphql subgraph with dataloader and router auth guard
- GraphQLModule: Apollo Federation 2 subgraph at /graphql

- UserResolver/RoleResolver: @key with @ResolveReference using DataLoader (ADR-035)

- DataScopeResolver: ScopeToken for visible class/student IDs (ADR-041)

- RouterAuthGuard: validate Router-Authorization header (ADR-036)

- DataLoaderService: REQUEST-scoped userLoader + roleLoader

- IamRepository.batchFindRoles: batch query for DataLoader

- IamService.getVisibleClassIds/getVisibleStudentIds: dataScope calculation

- app.module.ts: register PermissionGuard + RouterAuthGuard as APP_GUARD
2026-07-14 23:48:16 +08:00
SpecialX
5fcb831a18 feat(shared-ts): federation shared utilities for apollo subgraphs
- RouterAuthGuard: validate Router-Authorization header (ADR-036)

- DataLoader factory: request-scoped batching (ADR-035)

- ScopeTokenService: Redis-backed scope token (ADR-041)

- GraphqlContext: build context from HTTP headers

- FederationExceptionFilter: HTTP-to-GraphQL error mapping
2026-07-14 23:46:51 +08:00
SpecialX
3c2ea50c7f feat(infra): proto-to-graphql generator + debezium outbox connector
- M0: parse proto to generate Federation 2 subgraph SDL

- M0.5: Debezium Connect monitors 4 outbox tables

- docker-compose: extend Debezium profiles to default+p3+p4+p5+p6

- package.json: add proto:gen-graphql script
2026-07-14 23:45:32 +08:00
SpecialX
f212ba0813 docs(docs): known-issues ai 模块经验更新(9 RPC + 6 权限点 + 2 新经验)
gRPC server 8→9 RPC(新增 GenerateReport)

PermissionGuard 5→6 权限点(新增 ai:report:generate)

新增经验:Markdown 章节关键词提取 + main.py 模块级变量顺序
2026-07-14 23:02:01 +08:00
SpecialX
765f7da4c0 feat(msg): v2 ARB-013 topic 命名统一 + 考试事件消费
ARB-013 P0 修复:PRODUCER_TOPIC_MAP 从 edu.notification.* 改为 edu.notify.notification.*

kafka.consumer 新增 3 考试实时事件消费(exam.extended/force_submitted/question_reordered)

嵌套 payload 解包支持 + topic-map 扩展

新增 6 测试数据文件(docker-notify + 5 kafka 事件 json)

101 单元测试通过 + Docker 真实环境验证
2026-07-14 23:00:33 +08:00
SpecialX
ad39a3bb0f feat(iam): v2 用户管理 RPC + F12 httpOnly Cookie
admin-portal §2.3 P1 阻塞项补齐:CreateUser/UpdateUser/DeleteUser 3 RPC

iam.repository/service/grpc.controller 实现 3 用户管理方法(含 bcrypt + 审计)

iam.controller 新增 POST /v1/iam/users + DELETE /v1/iam/users/:id(@RequirePermission(IAM_USER_MANAGE))

iam.dto 新增 createUserSchema Zod 校验

F12 httpOnly Cookie:refresh_token 改为 httpOnly+Secure+SameSite=Strict Cookie 下发

extractRefreshToken 优先读 cookie 回退 body + buildRefreshTokenCookie/buildClearCookie
2026-07-14 22:59:28 +08:00
SpecialX
d11441c9a8 feat(core-edu): v2 P3.14 考试实时事件 + pino 修复
新增 3 RPC:ExtendExam/ForceSubmitExam/ReorderExamQuestions

新增 3 Kafka 事件:exam.extended/exam.force_submitted/exam.question_reordered

exams.service.ts 新增 3 方法 + Outbox 事务内写入 + TOPIC_MAP 映射

grpc.server.ts 注册 3 handler + grpc-smoke 测试

logger.ts pino 导入修复(import pino → import { pino })

27/27 smoke test 通过
2026-07-14 22:58:38 +08:00
SpecialX
aac26c7c6f feat(ai): v2 新增 GenerateReport RPC + ReportService
第 9 个 RPC GenerateReport(学情报告生成):data-ana 学情数据 → LLM 生成 → 结构化提取

新增 ReportService 业务编排层 + GenerateReportRequest/GeneratedReport 模型

gRPC servicer + HTTP POST /v1/ai/generate/report(权限 ai:report:generate)

proto_gen 重新生成 + 测试覆盖(servicer/service/HTTP/模型/权限 共 26 用例)

402 测试通过,覆盖率 88.5%
2026-07-14 22:57:57 +08:00
SpecialX
843b370b3d feat(shared-proto): ai/core_edu/iam proto v2 扩展
ai.proto: 新增 GenerateReport RPC + GenerateReportRequest/GeneratedReport message

core_edu.proto: 新增 ExtendExam/ForceSubmitExam/ReorderExamQuestions 3 RPC + message

iam.proto: 新增 CreateUser/UpdateUser/DeleteUser 3 RPC + 4 message
2026-07-14 22:57:18 +08:00
SpecialX
7545956202 docs(docs): v2.1 架构 spec 8 项调整
- Temporal 严格边界引入(AI 工作流 + Saga,CRUD 短事务禁用)

- CDC+Outbox 结合(Debezium Transaction Log Tailing,废弃轮询)

- DataLoader 强制(@key 解析器请求合并,消除 N+1)

- Router-Authorization 信任凭证(拒绝非 Router 的 GraphQL 请求)

- 外部 GraphQL + 内部 gRPC 边界明确

- Eager Invalidation + 乐观锁版本号回传

- Redis Pub/Sub 推送背板(边缘网关不挂 Kafka)

- ScopeToken 优化大规模 ID 列表传递
2026-07-14 22:55:56 +08:00
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
SpecialX
594a4e65fe fix(arch-scan): 修复 ts-scanner 误识别 Python 服务 + 扩展符号提取
- 新增 pyproject.toml 检测,跳过纯 Python 服务(ai/data-ana)和包(shared-py)

- 扩展符号提取:新增 TS_CONST_EXPORT_RE 匹配 camelCase/PascalCase 导出常量

- 新增 TS_TYPE_RE 匹配 export type alias

- 修复后 arch:scan 输出 22 模块 / 4715 符号 / 475 契约
2026-07-14 21:24:22 +08:00
SpecialX
0b858d9069 docs(docs): 新增 0020 Portal Shell 架构文档(C4+4+1+ADR) + 设计 spec v2.1 + 更新 0010/004 指向新架构 2026-07-14 18:34:40 +08:00
SpecialX
9db7fd917e feat(data-ana): v2 P6 硬化完成 + 6 新 RPC + Prometheus 监控
P6 硬化(5 项全部完成):

- CDC 多实例水平扩展: _INSTANCE_ID + get_lag() 真实 lag 计算

- ExamCache Redis 化: key data_ana:exam:{exam_id}, TTL 30 天 + 内存 LRU fallback

- ClickHouse TTL 归档: 5 表均加 TTL(1-3 年),分区级删除

- Prometheus 监控: 18 个指标(CDC/CH/ExamCache/DataScope/gRPC/业务)

- readyz 深度硬化: 4 依赖超时检查(CH 1s/Redis 200ms/iam 2s/CDC lag<1000)

v2 新增 6 个 RPC(analytics.proto 扩展为 18 RPC):

- GetStudentGrowth / GetAssignmentAnalysis / GetMasterySummary

- ListDiagnosticReports(占位,待 ai 服务)/ ListErrorBookItems / GetErrorBookStats

监控与可观测性: lifespan 预热 + gRPC ServerInterceptor + CDC 消费者指标

Docker 本地测试 19 项全部通过(healthz/readyz/metrics + 11 HTTP + 10 gRPC + ruff)

nextstep-v2.md: 上游需求对齐 + 下游要求(iam/core-edu/content/ai/SRE)
2026-07-14 18:07:17 +08:00
SpecialX
78e406b317 feat(content): v2 扩展 Elective/LessonPlan/CoursePlan 三业务域
新增 3 个业务域(10 RPC):
- ElectiveService: 选修课列表/学生选课记录/选课/退课(含容量与重复校验)
- LessonPlanService: 教师备课列表/学生备课列表(仅 published)/详情
- CoursePlanService: 学生课程计划列表/详情
- KnowledgeGraphService.GetKnowledgePath: 与 GetLearningPath 同实现

新增 4 张 MySQL 表(elective_courses/selections/lesson_plans/course_plans),含完整索引。

新增 11 个权限点,覆盖 admin/teacher/student/parent 四角色。

proto 由 4 Service/22 RPC 扩展至 7 Service/32 RPC,v1 全部 RPC 保持向后兼容。

修复 logger.ts pino 导入: default import 在 NodeNext ESM 下不可调用,
改用 named import(与 iam/msg/core-edu 对齐)。

Docker 本地测试全部通过(HTTP + gRPC 双协议),健康检查、
Elective/LessonPlan/CoursePlan CRUD、4 个新 gRPC Service 全部验证通过。

nextstep-v2.md 已创建,记录上下游依赖与 6 项联调待办。
2026-07-14 17:54:37 +08:00
SpecialX
abde336876 chore(deps): 更新根 package.json 依赖 + pnpm-lock.yaml 同步
Some checks failed
CI / quality-ts (push) Failing after 6s
CI / quality-go (push) Failing after 26s
CI / quality-proto (push) Failing after 6s
CI / deploy (push) Has been skipped
2026-07-14 16:04:48 +08:00
SpecialX
2796d7c88f feat(infra): api-gateway 环境变量补全 + build context 修复 + docker-compose.test 新增 2026-07-14 16:04:20 +08:00
SpecialX
a70977ad4b feat(api-gateway): admin 路由组 + BFF 路径重写 + announcements 路由 + Dockerfile 修复 + nextstep v2 文档 2026-07-14 16:03:38 +08:00
SpecialX
9fd7c018c2 feat(push-gateway): config 扩展 + kafka consumer + ws handler + nextstep 文档 2026-07-14 16:03:17 +08:00
SpecialX
5a88c8b45d feat(parent-bff): graphql schema 扩展 + extended-resolvers + grpc factory + nextstep 文档 2026-07-14 16:02:49 +08:00
SpecialX
422b55f901 feat(student-bff): extended queries/mutations resolvers + Dockerfile + nextstep 文档 2026-07-14 16:01:20 +08:00
SpecialX
895a060491 feat(teacher-bff): admin 命名空间 + 5 个 gRPC client + health probes + merge-resolvers + nextstep 文档 2026-07-14 16:00:46 +08:00
SpecialX
7b790f1276 feat(ai): gRPC clients 扩展 + server interceptors + proto_gen + 测试 + nextstep 文档 2026-07-14 15:59:41 +08:00
SpecialX
fb23c5234e feat(msg): announcements 公告模块 + sendBatch 批量优化 + 权限扩展 + nextstep 文档 2026-07-14 15:57:41 +08:00
SpecialX
7dd5c44406 feat(core-edu): admin/dashboard/leave-requests 模块 + gRPC + 状态机测试 + nextstep 文档 2026-07-14 15:56:10 +08:00
SpecialX
d260df864c feat(iam): 角色权限管理 + 权限缓存 + 指标 + 鉴权中间件增强 + nextstep 文档 2026-07-14 15:55:39 +08:00
SpecialX
e9d3030f2f feat(shared-ts): 同步 3 个 BFF GraphQL schema + downstream-client/logger/outbox 增强 2026-07-14 15:51:36 +08:00
SpecialX
774af93d76 feat(shared-proto): core_edu proto 扩展 admin/dashboard/leave-requests/grpc 定义 2026-07-14 15:48:20 +08:00
SpecialX
81a539b9ab chore(deps): 统一依赖管理 - pnpm 11 + node:22 + golang:1.25 + python:3.12 + shared-* 集中化
Some checks failed
CI / quality-ts (push) Failing after 6s
CI / quality-go (push) Failing after 25s
CI / quality-proto (push) Failing after 6s
CI / deploy (push) Has been skipped
- Node.js 统一到 node:22-alpine,Go 统一到 golang:1.25-alpine,Python 统一到 python:3.12-slim

- pnpm 升级到 11.13.0(corepack),新增 allowBuilds 白名单解决 ERR_PNPM_IGNORED_BUILDS

- 新增 packages/shared-py 集中 Python 共享依赖,shared-ts 补充 graphql-yoga/prom-client

- api-gateway 修复 go.mod 的 shared-go 依赖 + Dockerfile 改用 repo 根作 context

- Python 服务(data-ana/ai)Dockerfile 改用 repo 根作 context + 声明 uv workspace sources

- 16 个服务的 Dockerfile + CI + docker-compose.tools.yml 全部对齐版本矩阵

- known-issues.md 沉淀 9 条 pnpm 11 / uv workspace / Go shared-go 迁移经验

- 验证:4 服务完全成功(api-gateway /healthz 200),其余 install 成功(build 失败为预存 TS 错误)
2026-07-14 12:04:49 +08:00
SpecialX
74077c7083 docs(parent-portal): 恢复 nextstep.md v1 原貌 + 新增 nextstep-v2.md 核查报告
v1 保持原样(2026-07-13 初版下游待办)

v2 新增(2026-07-14 核查结果):1 项已完成(pnpm-lock),4 项仍未完成(端点路径/Docker/schema/api-gateway 镜像)

v2 新发现:extended-resolvers.ts 存在但未集成且引用不存在的类型;parent-bff Dockerfile pnpm 版本未固定
2026-07-14 10:14:43 +08:00
SpecialX
0066afc55e feat(teacher-portal): v2 下游核查 + push-gateway 接入 + 测试扩展至 87 + ui-components 12/12
v2 核查结论:

- iam/push-gateway/api-gateway 已就绪

- teacher-bff teacher 域仍是 P2 占位(56/61 operations 不可用)

- 5 个 gRPC target 留空走降级模式 B

- 保留 MSW mock,记录 12 项 teacher-bff 待补工作到 nextstep-v2.md

v2 完成工作:

- push-gateway WebSocket 接入(环境变量 + URL query token + Reconnect 协议)

- 单元测试扩展(usePermission 15 + useAuth 9,总计 87/87 passed)

- ui-components 剩余 3 组件(Chart/Calendar/RichTextEditor,12/12)

- 设计令牌完整迁移(无 hsl/hex 字面量)

- i18n 5/55 页面 + 26 模块 key

- 性能优化(size-limit 9 项 + 5 页面懒加载)

- useAuth 迁移阻塞核查(iam 未实现 Set-Cookie,修正 v1 假设)

文档:新增 nextstep-v2.md;workline.md §5.7 添加 v2 工作记录。

验证:typecheck + lint + 87/87 tests + arch:scan 全部通过。
2026-07-14 08:47:18 +08:00
SpecialX
ae6fe23be6 docs(student-portal): nextstep-v2 二次核查下游服务实现状态 2026-07-14 08:43:45 +08:00
SpecialX
21f2485749 docs(student-portal): nextstep-v2 核查下游服务实现状态+记录42个resolver未装配问题 2026-07-14 08:36:02 +08:00
SpecialX
41179ff0a9 docs(parent-portal): nextstep.md v2 核查下游服务完成情况
v2 核查结果:parent-bff pnpm-lock 已添加,但端点路径/schema/Docker 构建/extended-resolvers 集成仍未完成

api-gateway Docker 构建仍失败(golang:1.22-alpine 无法拉取)

parent-portal 自身 Docker 镜像构建成功,容器 healthy,typecheck + lint 零错误
2026-07-14 08:29:25 +08:00
SpecialX
0b42302a64 docs(admin-portal): 新增 nextstep-v2.md 记录下游核查结果
v1 声称完成的下游工作经核查实际未完成:
- api-gateway: /api/admin/graphql 路由未注册,go vet 编译失败
- teacher-bff: resolver 已完成但 schema 未同步(命名空间 vs 扁平)
- iam: proto 缺 BatchGetUsers rpc 声明

v2 记录详细核查证据和修复要求
2026-07-14 08:26:27 +08:00