fix: 修复集成测试中发现的全部 bug — 15 服务端到端验证通过

修复涵盖 6 大类问题:

1. api-gateway
   - 路径前缀剥离 /api 而非 /api/v1,保留下游 /v1/ controller 前缀
   - JWKS URL 默认值修复
   - publicPaths 白名单对齐 /v1/iam/*

2. iam
   - iam.module.ts exports 补充 PermissionCacheService 和 IamRepository
   - main.ts resolveProtoPath() 多路径探测 proto 文件

3. core-edu
   - app.module.ts AuthMiddleware 全局注册

4. BFF 层 GraphQL 端点(teacher-bff / parent-bff / student-bff)
   - teacher-bff: mock dataScope OWN→SELF 对齐 GraphQL enum;WHATWG Request header .get() 提取
   - parent-bff: handleNodeRequestAndResponse 不存在 → 直接 yoga(req,res);WHATWG Request header .get() 提取
   - student-bff: auth.resolver 移除 ActionState 信封返回扁平对象;WHATWG Request header .get() 提取

5. ai
   - Kafka 事务降级 + 10s 超时
   - gRPC 拦截器降级
   - dev mode 禁用事务模式

6. 前端 + 共享包
   - teacher-portal: MF 插件条件实例化 + transpilePackages + extensionAlias
   - ui-components: error-boundary.tsx 添加 use client
   - ui-tokens: tailwind-theme.css 移除 @layer base
   - shared-ts: 导出从源码改为 dist 编译产物;OutboxModule global:true

7. infra
   - .gitignore 补充 keys/ *.pem *.key secrets/ 排除规则
   - infra/init-sql/02-all-services-schema.sql 36 张表 DDL

验证结果:
- TS typecheck: 19 个 workspace 项目全部通过
- Go vet + Ruff: 通过
- 15 服务全部启动成功
- 3 个 BFF GraphQL 端点 + 4 个前端页面全部 200
- Gateway → iam → core-edu 端到端链路验证通过

AI identity: trae-main(集成测试修复会话)
This commit is contained in:
SpecialX
2026-07-11 01:41:46 +08:00
parent c6362f4b04
commit 61d824924a
35 changed files with 1020 additions and 192 deletions

View File

@@ -19,7 +19,7 @@
* - volumeThreshold: 10 (最少 10 次调用才评估)
* - rollingCountTimeout: 60000 (1 分钟滚动窗口)
*/
import { Injectable } from "@nestjs/common";
import { Injectable, Optional } from "@nestjs/common";
import CircuitBreaker from "opossum";
import promClient from "prom-client";
import type { DownstreamClient, CallOptions } from "@edu/shared-ts/bff";
@@ -92,7 +92,7 @@ export class CircuitBreakerService {
private readonly breakers = new Map<string, CircuitBreaker>();
private readonly config: BreakerConfig;
constructor(config?: Partial<BreakerConfig>) {
constructor(@Optional() config?: Partial<BreakerConfig>) {
this.config = { ...DEFAULT_CONFIG, ...config };
}

View File

@@ -11,8 +11,9 @@
* 集成方式: GraphQL Yoga 作为 Express middleware 挂载到 NestJS HTTP Adapter,
* 路径 POST /graphql,开发环境启用 Playground.
*/
import { promises } from "node:fs";
import { promises, existsSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { createYoga, type YogaServerInstance } from "graphql-yoga";
import { makeExecutableSchema } from "@graphql-tools/schema";
import type { Request, Response } from "express";
@@ -54,11 +55,25 @@ export interface StudentBffContext {
/**
* GraphQL schema 文件路径.
* 多路径探测兼容从项目根目录或服务目录运行pnpm --filter cwd 为服务目录).
*/
const SCHEMA_PATH = path.resolve(
process.cwd(),
"packages/shared-ts/contracts/graphql/student-bff.schema.graphql",
);
const _schemaDir = path.dirname(fileURLToPath(import.meta.url));
const SCHEMA_CANDIDATES = [
path.resolve(
process.cwd(),
"packages/shared-ts/contracts/graphql/student-bff.schema.graphql",
),
path.resolve(
process.cwd(),
"../../packages/shared-ts/contracts/graphql/student-bff.schema.graphql",
),
path.resolve(
_schemaDir,
"../../../../../packages/shared-ts/contracts/graphql/student-bff.schema.graphql",
),
];
const SCHEMA_PATH: string =
SCHEMA_CANDIDATES.find((p) => existsSync(p)) ?? SCHEMA_CANDIDATES[0]!;
/**
* 加载 schema SDL 文本.
@@ -107,7 +122,15 @@ export async function createStudentBffYoga(
>({
schema,
graphqlEndpoint: "/graphql",
context: ({ req }): StudentBffContext => {
// graphql-yoga v5request 是 WHATWG Requestheaders 需用 .get() 提取
context: ({ request }): StudentBffContext => {
const req = {
headers: {
"x-user-id": request.headers.get("x-user-id") ?? undefined,
"x-request-id": request.headers.get("x-request-id") ?? undefined,
"x-user-roles": request.headers.get("x-user-roles") ?? undefined,
},
} as unknown as Request;
const userId = extractUserIdFromRequest(req);
const traceId = extractTraceIdFromRequest(req);
const userRoles = extractUserRolesFromRequest(req);