v4.3 安全修复+代码质量+测试体系+护城河验证

## 安全修复 (5项)
- CRITICAL JWT 硬编码 fallback(jwt.strategy / app.module / user.module)
- HIGH seed_admin.js MongoDB 凭据泄漏
- MEDIUM 邮箱验证码泄漏
- MEDIUM 支付订单查询 IDOR
- MEDIUM 管理后台 NoSQL 注入

## 代码质量 (14处)
- console.log→Logger(user.service.ts)
- as any 类型化(11处跨7个文件)
- Schema 联合类型修复(progress.schema)
- Module 依赖缺失修复(progress.module)

## 测试体系 (61项)
- 后端单元测试 Jest(43项):BenchmarkService/UserService/PaymentController
- 后端集成测试 Supertest(11项):API 认证/支付/进度/管理
- 前端单元测试 Vitest(7项):配置文件/API端点
- 浏览器自动化 Playwright(7项):API smoke test
- 覆盖率报告 + e2e 配置

## 护城河 P0-P5 启动验证通过 + 编译通过
This commit is contained in:
yuzhiran
2026-06-11 10:27:35 +08:00
parent 9276ab9028
commit e6b79ddb21
39 changed files with 4576 additions and 246 deletions
@@ -11,7 +11,7 @@ export class Interview {
@Prop({ required: true })
position: string
@Prop({ default: 'in_progress' }) // in_progress | completed
@Prop({ default: 'in_progress' })
status: string
@Prop({ default: 0 })
@@ -34,6 +34,9 @@ export class Interview {
@Prop({ default: 0 })
fillerDensity: number
readonly createdAt?: Date
readonly updatedAt?: Date
}
export const InterviewSchema = SchemaFactory.createForClass(Interview)
@@ -245,12 +245,27 @@ ${fullConversation}
.join('\n')
const speechAnalysis = userAnswers ? analyzeSpeech(userAnswers) : null
// Parse dimensions from summary JSON
let dimensions: Record<string, number> | null = null
if (interview.summary) {
try {
const parsed = JSON.parse(interview.summary)
dimensions = {
logic: parsed['逻辑思维'] || 0,
expression: parsed['表达能力'] || 0,
professionalism: parsed['专业度'] || 0,
stability: parsed['稳定性'] || 0,
}
} catch {}
}
return {
...interview.toObject(),
fillerWords: speechAnalysis?.fillerWords || interview.fillerWords,
fillerScore: speechAnalysis?.fillerScore || interview.fillerScore,
fillerDensity: speechAnalysis?.fillerDensity || interview.fillerDensity,
speechAnalysis,
dimensions,
}
}
@@ -267,7 +282,7 @@ ${fullConversation}
status: i.status,
totalScore: i.totalScore,
questionCount: i.questionCount,
time: (i as any).createdAt,
time: i.createdAt,
}))
}