SpecialX
f92fdf8efe
feat(portal-shell): wire AppFrame + navigation + permission filter (P1-1)
...
实现 ARCHITECTURE.md §10 P1-1:
- 新增 src/shared/lib/navigation.ts:27 项静态导航注册表,
按 teacher/student/parent/admin 四角色分区,group 字段用于角色过滤
- 新增 src/app/shell/layout.tsx:RSC AppFrame,从 headers() 读取
middleware 注入的身份头,batchCheckRoutePermission 按位图二次过滤
- 新增 src/shared/components/layout/user-menu.tsx:顶部用户菜单,
显示 userId + role,登出 POST /api/auth/logout
- 新增 src/shared/lib/__tests__/navigation.test.ts:P1-1 验收单测
(7 用例:href 登记一致性 + 4 角色隔离 + 权限检查)
- 修改 src/shared/lib/route-permissions.ts:补全 7 个列表页根路由
的 EXACT 登记(/shell/admin/announcements、/shell/admin/classes、
/shell/teacher/exams 等),与 PREFIX 表互补避免 catch-all 拒绝
验收:
- vitest run navigation → 7/7 passed
- tsc --noEmit 通过;eslint(5 文件)通过
回填 ARCHITECTURE.md §10 P1-1 状态为 ✅ ,附验收证据。
关联:ARCHITECTURE.md §7.2 AppFrame / §10 P1-1
2026-07-22 12:17:16 +08:00
SpecialX
dc13a2afb4
docs(portal-shell): backfill ARCHITECTURE.md §10 P0 completion status
...
- §10 P0 表格新增"状态"列,全部标记 ✅
- 新增"P0 验收证据(2026-07-22)"小节,逐条附命令/文件引用
- 文档头部状态行从"待实施"改为
"P0 已完成 + P1 进行中"
- 验收依据:
P0-1 login API 401 实测
P0-2 middleware + forbidden page 代码
P0-3 localStorage 仅匹配删除注释
P0-4 getDefaultConfig 实现
P0-5 instrumentation register() 实现
P0-6 vitest 27/27 通过
P0-7 eslint 0 errors
P0-8 git status 干净
2026-07-22 11:42:02 +08:00
SpecialX
cfb7b005fd
feat(portal-shell): v2.1 P0 auth + middleware + login + graphql proxy
...
- 新增 ARCHITECTURE.md v3.0:portal-shell 架构权威文档
涵盖 §3.4 V3-A2/A3 认证链、§4 GraphQL 联邦、§5 安全、
§6 部署、§10 P0-P3 验收清单
- 新增 middleware.ts:认证 + 路由门禁
httpOnly cookie edu_session(JWT)读取
DEV_MODE 合成 dev-user/teacher 身份(NODE_ENV!=production &&
NEXT_PUBLIC_DEV_MODE=true)
生产模式 jose JWKS RS256 验签(iss/aud 校验)
路由权限位图注入 x-user-id/x-user-role/x-user-permissions 头
/shell/** 强制 checkRoutePermission,拒绝跳 /shell/forbidden
- 新增 instrumentation.ts:生产环境 DEV_MODE 强制 false
防止生产环境误开 DEV_MODE 合成身份
- 新增 app/api/auth/login/route.ts + logout/route.ts
登录走 api-gateway /v1/iam/login
设置 httpOnly + Secure + SameSite=Strict cookie
- 新增 app/api/graphql/route.ts:同域 GraphQL 代理
转发到 apollo-router,注入 router-authorization 头
- 新增 app/login/page.tsx + login-form.tsx
zod 表单校验,next 参数支持
- 新增 app/shell/forbidden/page.tsx:403 页面
- 更新 route-permissions.ts:补全 P0 路由权限映射
- 更新 permission-bitmap.ts(shared-ts):位图编码/解码
- 更新 apollo-client.ts:DEV_MODE APQ 关闭,错误处理
- 更新 config-fetcher.ts:config-service 直连降级
- 更新 ApolloProvider.tsx:SSR/RSC 兼容
- 更新 eslint.config.js:design-tokens/no-hardcoded-fonts
白名单调整
2026-07-22 11:35:36 +08:00
SpecialX
682f323bad
chore(infra): docker dev-apps stack + apollo-router v1.45 compat
...
- 新增 docker-compose.dev-apps.yml:7 个应用服务容器化
(iam/classes/core-edu/content/msg/push-gateway/api-gateway)
+ apollo-router override
- 新增 apollo-router dev-apps-entrypoint.sh / dev-apps-supergraph.yaml
仅等待 5 个子图(iam/core-edu/content/msg/config-service)
避免等待未启动的 ai/data-ana
- router.yaml:移除 v1.45 不兼容键
(require_manifest/manifest_path/max_cost/max_batch_size)
移除 ELv2 受限特性(persisted_queries/limits.max_depth)
自托管无 GraphOS license
- docker-compose.yml:config-service 添加 NODE_ENV=production
修复 pino-pretty devDep 误用
apollo-router 添加 APOLLO_PERSISTED_QUERIES env
- services/{classes,core-edu,content,config-service}/Dockerfile
重写为 repo 根 context + shared-ts/shared-proto 工作区依赖
+ --ignore-scripts
修复 ERR_PNPM_WORKSPACE_PKG_NOT_FOUND 与 ERR_PNPM_IGNORED_BUILDS
- api-gateway healthcheck:wget --spider 改为 wget -O /dev/null
修复 busybox 对 200+body 误报 exit 8
2026-07-22 11:35:02 +08:00
SpecialX
f586a0b19e
feat(portal-shell): v2.0 P1-P4 token migration + unit tests + prod endpoint + e2e
...
P1: 31 widget 旧纸感令牌批量迁移到 shadcn 标准(1104 次替换)
- bg-paper→bg-background / bg-surface→bg-card / text-ink→text-foreground
- 保留 button.tsx 中 bg-accent(shadcn 标准 hover 语义令牌)
P2: v2.0 新增组件单元测试补齐(5 文件 81 用例)
- permission-bitmap: 24 用例(含 GRADE_READ 重复去重)
- route-permissions: 26 用例(4 张表优先级 + AND/OR 语义)
- notify: 12 用例(sonner toast 双重性质 vi.hoisted mock)
- use-error-report: 9 用例(jsdom Blob vi.stubGlobal mock)
- plugin-boundary: 10 用例(错误边界 + 骨架变体)
P3: 错误上报端点生产替换(后端 /api/v1/log)
- api-gateway: internal/log/handler.go(slog 结构化日志,64KB 限制,204 返回)
- main.go: 注册 POST /api/v1/log 路由
- useErrorReport: 环境感知端点(prod→/api/v1/log,dev→/api/log)
P4: E2E 测试(3 文件 30 用例)
- streaming: 4 用例(React 19 use() + Suspense,act 包裹 render)
- error-boundaries: 6 用例(三级错误边界层级 L1/L2/L3)
- security-boundaries: 20 用例(L1 角色门禁 + L2 权限点 + L3 数据范围)
- vitest setup: IS_REACT_ACT_ENVIRONMENT + jest-dom matchers
验证:typecheck 0 错误 / lint 0 错误 / build 6 路由 / 206 测试全部通过
2026-07-17 16:49:00 +08:00
SpecialX
9cedf0c437
feat(portal-shell): v2.0 P0 shadcn standardization + security + streaming + error handling
...
- shadcn/ui 标准化:废弃纸感令牌,统一 bg-background/text-foreground 等
- Tailwind v4 + @theme inline,移除 tailwind.config.js
- React 19 use() + Suspense 流式渲染,首屏骨架秒出
- 三级错误边界:Route → Section → Widget 层层兜底
- 错误上报:useErrorReport → sendBeacon → /api/log mock 端点
- 三层安全边界:L1 角色门禁 / L2 权限点门禁 / L3 数据范围
- 权限位图 base36 压缩:67 权限点 → ~14 字符,JWT 体积减少 ≥ 99%
- notify 统一 Toast 封装,禁止业务直接 import sonner
- PluginBoundary 替代 PluginLoader(错误边界 + Suspense + Skeleton 三件套)
验证:typecheck 0 错误 / lint 0 错误 / build 6 路由生成成功
2026-07-17 16:10:05 +08:00
SpecialX
f7e52b5b7f
docs(portal-shell): update README to v1.1 with data layer and GraphQL hardening
...
- 版本 1.0 -> 1.1,日期 2026-07-17
- 新增 §13 数据访问层与 GraphQL 安全栈(6 子节)
- 更新 §5/§9.6/§10/§11/§12/附录 A/B/C
- 修正 004 §16.5 测试数(admin 31->4,sidebar 5->9)
- arch:scan 通过(TS 20 模块/4803 符号)
2026-07-17 13:47:40 +08:00
SpecialX
f8db1bfe80
docs(docs): add portal-shell data layer and GraphQL hardening known-issues
...
§1.11 Apollo Router 新增 4 条全局经验:
- PQ Manifest + require_manifest 配置
- limits 深度/成本/批量限制
- introspection 环境变量控制
- entrypoint.sh manifest 校验
§2.17 portal-shell 新增 15 条模块经验:
- Widget 内联 gql 废弃 + 4 层数据访问分层
- graphql-codegen skipDocumentsValidation
- useNotifications 命名冲突
- APQ + PQ Manifest 生成
- Windows ESM 动态 import 路径
- apollo-router PQ manifest 挂载 + 安全限制
- Resolver @RequirePermission 字段级守卫
- TS interface 不满足 Record 约束
- parent.test.tsx 可选链
- PowerShell heredoc / commitlint 限制
2026-07-17 13:39:16 +08:00
SpecialX
bbb43a210f
docs(docs): sync 004 with portal-shell data layer and GraphQL hardening
...
新增 §11.7 portal-shell 前端数据访问层 + GraphQL 安全栈:
- §11.7.1 四层数据访问分层(Widget → API → Operations → Hook)
- §11.7.2 GraphQL 安全栈(APQ + PQ Manifest + 深度/成本限制)
- §11.7.3 Resolver 权限守卫审计与补齐
新增 §16.5 portal-shell 数据抽象与 GraphQL 加固子阶段(M1-M4 完成)
新增 ADR-042(前端数据访问四层分层)、ADR-043(PQ Manifest + APQ 安全加固)
更新 §16.4 关联 spec 文档列表
2026-07-17 13:38:16 +08:00
SpecialX
9bee920e4d
test(portal-shell): add security stack tests for PQ manifest and APQ
...
Covers v2.1 M3 安全加固验证:
- PQ Manifest 完整性(6 cases):DocumentNode 校验、sha256 稳定性、确定性、唯一性、manifest 文件有效性、hash 一致性
- Query depth limit(2 cases):11 层嵌套构造、合法查询构造(实际拒绝由 apollo-router limits.max_depth=10 执行)
- APQ behavior(2 cases):默认启用、NEXT_PUBLIC_APOLLO_APQ=false 关闭
测试结果:95/95 passed (85 原有 + 10 新增)
2026-07-17 13:35:37 +08:00
SpecialX
caa90eba85
feat(infra): enable apollo-router APQ + manifest + depth/cost limits
...
Task 14 of portal-shell data abstraction plan (M3 security).
router.yaml:
- persisted_queries: enabled + require_manifest (env-controlled)
- limits: max_depth=10, max_cost=1000, max_batch_size=5
- introspection: env-controlled (prod=false, dev=true)
docker-compose.yml:
- Mount portal-shell/public/pq-manifest.json as read-only volume
- Add APOLLO_REQUIRE_PQ_MANIFEST + APOLLO_ROUTER_INTROSPECTION env vars
- Dev defaults preserve current behavior (manifest optional)
entrypoint.sh:
- Pre-start check: if require_manifest=true, fail fast when manifest missing
- Dev mode: warn but continue when manifest absent
Production enables strict mode via env:
APOLLO_REQUIRE_PQ_MANIFEST=true
APOLLO_ROUTER_INTROSPECTION=false
2026-07-17 13:32:46 +08:00
SpecialX
b30d43f983
feat(portal-shell): enable Apollo Client APQ + PQ manifest generator
...
Task 12-13 of portal-shell data abstraction plan (M3 security).
APQ (Automatic Persisted Queries):
- Add createPersistedQueryLink with sha256 to apollo-client.ts
- Production: client sends only query hash, not plaintext query
- Dev: NEXT_PUBLIC_APOLLO_APQ=false to disable for debugging
- Prevents attackers from crafting arbitrary queries via DevTools
PQ Manifest generator:
- New scripts/generate-pq-manifest.ts iterates operations barrel
- Outputs public/pq-manifest.json (sha256 -> query text whitelist)
- prebuild hook: codegen + generate-pq-manifest before next build
- 51 queries currently registered
- crypto-hash dependency added
- typecheck + lint (0 errors) + test (85/85) verified
2026-07-17 13:31:11 +08:00
SpecialX
1b5781bf42
fix: add missing @RequirePermission decorators
...
Adds @RequirePermission to 19 TS GraphQL resolvers across 5
subgraphs (iam, config-service, core-edu, content, msg) per
audit report §6.1. Maps: iam user/role -> IAM_USER_READ;
config-service 5 queries -> CONFIG_USER; core-edu classInfo ->
CLASS_READ, exam -> EXAM_READ, grade -> GRADE_READ, homework
-> HOMEWORK_READ, datascope visibleGrades/visibleExams ->
GRADE_READ/EXAM_READ; content chapter/knowledgePoint/question/
textbook -> CONTENT_*_READ; msg notifications ->
MSG_NOTIFICATION_READ, template -> MSG_NOTIFICATION_MANAGE.
Federation resolveReference left unguarded. Python subgraphs
(data-ana, ai) deferred to follow-up infrastructure work.
2026-07-17 13:26:58 +08:00
SpecialX
315b954998
docs(docs): add GraphQL @auth audit report
...
Audits 50 resolvers across 8 Apollo Federation subgraphs (iam,
config-service, classes, core-edu, content, msg, data-ana, ai).
Coverage: 18 guarded, 32 missing (36%). TS subgraphs: 35 total,
16 guarded, 19 missing (45.7%). Python subgraphs: 15 total, 2
guarded, 13 missing (13.3%). Documents AuthMiddleware /graphql
coverage gaps and Python resolver permission infrastructure as
follow-up items.
2026-07-17 13:20:30 +08:00
SpecialX
2910a90271
feat(portal-shell): extract domain API layer and migrate 31 widgets
...
Task 4-10 of portal-shell data abstraction plan (M1-M2).
Add 7 domain API modules under src/lib/api/ (parent/admin/teacher/
student/universal/sidebar/topbar), each exposing semantic hooks that
wrap useWidgetQuery/useWidgetMutation and return flattened domain
models. Widget code now imports from @/lib/api instead of inlining
gql literals.
- 31 widgets migrated (gql literal count in widgets: 0)
- 7 test files (85 cases, all passing)
- topbar.useNotifications renamed to useNotificationBell to avoid
barrel export collision with universal.useNotifications
- typecheck + lint (0 errors) + test (85/85) verified
2026-07-17 13:07:24 +08:00
SpecialX
f623dcf4a7
feat(portal-shell): extract gql documents to operations layer
...
M1 Task 3: 从 31 widget 抽取 51 个 gql 文档到 7 个 operations 文件
- universal(7) + sidebar(3) + topbar(3) + teacher(6) + student(8) + parent(4) + admin(20) = 51 DOC
- operations/index.ts barrel 统一出口
- codegen.yml 启用 documents + skipDocumentsValidation(services 子图字段待补齐)
- 生成 types.ts (28KB) + operations.ts (10KB)
2026-07-17 12:37:36 +08:00
SpecialX
7c234947e1
feat(portal-shell): add graphql-codegen configuration
...
M1 Task 2: 配置 graphql-codegen 与 federation schema 预处理
- codegen.yml: schema 从 combined-schema.graphql 读取(federation 已剥离)
- scripts/normalize-schema.ts: 把 7 个子图的 extend type Query 合并为 type Query
- package.json: 新增 codegen/codegen:watch scripts + 4 个 codegen deps + tsx
- .gitignore: 忽略 src/lib/api/__generated__/
- documents 配置暂注释,Task 3 创建 operations 文件后启用
2026-07-17 12:12:37 +08:00
SpecialX
989603e318
feat(portal-shell): add lib/api skeleton with errors and types
...
M1 Task 1: 创建 4 层数据抽象层的骨架文件
- errors.ts: ApiError + GraphQLErrorCode 枚举
- types.ts: Pagination / PaginatedResult / UseQueryResult / UseMutationResult
- internal.ts: normalizeError 把 ApolloError 转为 ApiError
- index.ts: barrel 出口
2026-07-17 12:06:01 +08:00
SpecialX
117c89396d
docs(portal-shell): add implementation plan for data abstraction & GraphQL hardening
...
- Plan: 20 tasks across M1-M4 phases
- Spec: fix useWidgetMutation destructure (object, not array)
2026-07-17 12:03:03 +08:00
SpecialX
135efa5ee5
docs(portal-shell): add data abstraction and GraphQL hardening spec
...
设计 portal-shell 数据抽象层与 GraphQL 安全加固方案:
- 4 层数据访问分层(Widget -> API -> Operations -> Hook)
- 31 个 widget 全量迁移到 lib/api/ 抽象层
- graphql-codegen 集成,消除手写类型
- Apollo Router 持久化查询(APQ + manifest)防查询探测
- 深度/复杂度限制(max_depth=10, max_cost=1000)
- 8 个子图字段级 @auth 审计与补齐
关联:portal-shell spec v2.1、004 §16、project_rules §3.8/§4
2026-07-17 11:56:35 +08:00
SpecialX
80e6468d62
docs(docs): sync 004 to v2.1 with apollo federation and portal-shell
2026-07-15 08:32:12 +08:00
SpecialX
83b6919185
feat(api-gateway): retire teacher/student/parent-bff, route GraphQL to apollo-router
...
v2.1 M9+M10: BFF layer and old portals retired.
- api-gateway: remove TeacherBffURL/StudentBffURL/ParentBffURL config
- api-gateway: add ApolloRouterURL config and /api/graphql route
- api-gateway: /api/admin/graphql now proxies to apollo-router
- api-gateway: health checks now ping apollo-router instead of BFF
- deploy.yml: replace teacher-bff service block with apollo-router
- deploy.yml: add config-service service block (M3 dependency)
- deploy.yml: remove teacher-portal and admin-portal service blocks
- source code in services/{teacher,student,parent}-bff/ and apps/*-portal/ retained for rollback
2026-07-15 08:14:24 +08:00
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