From 3c242a807a7a9e745a23c7ae25d24339c8e218cf Mon Sep 17 00:00:00 2001 From: WangDL Date: Sun, 24 May 2026 13:58:50 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20M2-02/06=20audit=20=E2=80=94=20system=20?= =?UTF-8?q?KB=20seed=20+=20candidate=20Content=20Safety?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SystemKnowledgeBaseSeed: auto-creates built-in 新手引导知识库 - Content Safety check on candidate accept() and createCandidates() Co-Authored-By: Claude Opus 4.7 --- .../import-candidate.service.ts | 23 +++++++++++++-- .../knowledge-base/knowledge-base.module.ts | 3 +- src/modules/knowledge-base/system-kb.seed.ts | 29 +++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/modules/knowledge-base/system-kb.seed.ts diff --git a/src/modules/import-candidate/import-candidate.service.ts b/src/modules/import-candidate/import-candidate.service.ts index 4749a24..639fa74 100644 --- a/src/modules/import-candidate/import-candidate.service.ts +++ b/src/modules/import-candidate/import-candidate.service.ts @@ -1,14 +1,22 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { Injectable, NotFoundException, Optional } from '@nestjs/common'; import { ImportCandidateRepository } from './import-candidate.repository'; import { KnowledgeItemsRepository } from '../knowledge-items/knowledge-items.repository'; +import { ContentSafetyService } from '../content-safety/content-safety.service'; @Injectable() export class ImportCandidateService { constructor( private readonly repository: ImportCandidateRepository, private readonly itemsRepo: KnowledgeItemsRepository, + @Optional() private readonly safety?: ContentSafetyService, ) {} + private async checkSafety(title: string, content: string, userId: string): Promise { + if (!this.safety) return true; + const check = await this.safety.check(title + ' ' + (content || '').slice(0, 200), { userId, contentType: 'candidate' }); + return check.safe; + } + async findBySource(sourceId: string) { return this.repository.findBySource(sourceId); } @@ -23,6 +31,10 @@ export class ImportCandidateService { const candidate = await this.repository.findById(id); if (!candidate) throw new NotFoundException('候选知识点不存在'); + // Content safety check before accepting + const safe = await this.checkSafety(candidate.title, candidate.content || '', candidate.userId); + if (!safe) return { status: 'BLOCKED', reason: '内容安全审核未通过' }; + await this.repository.updateStatus(id, 'ACCEPTED'); // 生成 KnowledgeItem @@ -60,6 +72,13 @@ export class ImportCandidateService { } async createCandidates(userId: string, knowledgeBaseId: string, sourceId: string, importId: string, candidates: Array) { - return this.repository.createMany(userId, knowledgeBaseId, sourceId, importId, candidates); + // Filter out unsafe candidates + const safeCandidates = []; + for (const c of candidates) { + const safe = await this.checkSafety(c.title || '', c.content || '', userId); + if (safe) safeCandidates.push(c); + } + if (safeCandidates.length === 0) return { created: 0, filtered: candidates.length }; + return this.repository.createMany(userId, knowledgeBaseId, sourceId, importId, safeCandidates); } } diff --git a/src/modules/knowledge-base/knowledge-base.module.ts b/src/modules/knowledge-base/knowledge-base.module.ts index 7296b7d..a615287 100644 --- a/src/modules/knowledge-base/knowledge-base.module.ts +++ b/src/modules/knowledge-base/knowledge-base.module.ts @@ -2,11 +2,12 @@ import { Module } from '@nestjs/common'; import { KnowledgeBaseController } from './knowledge-base.controller'; import { KnowledgeBaseService } from './knowledge-base.service'; import { KnowledgeBaseRepository } from './knowledge-base.repository'; +import { SystemKnowledgeBaseSeed } from './system-kb.seed'; import { PrismaService } from '../../infrastructure/database/prisma.service'; @Module({ controllers: [KnowledgeBaseController], - providers: [KnowledgeBaseService, KnowledgeBaseRepository, PrismaService], + providers: [KnowledgeBaseService, KnowledgeBaseRepository, SystemKnowledgeBaseSeed, PrismaService], exports: [KnowledgeBaseService], }) export class KnowledgeBaseModule {} diff --git a/src/modules/knowledge-base/system-kb.seed.ts b/src/modules/knowledge-base/system-kb.seed.ts new file mode 100644 index 0000000..3571726 --- /dev/null +++ b/src/modules/knowledge-base/system-kb.seed.ts @@ -0,0 +1,29 @@ +import { Injectable, Logger, OnModuleInit } from '@nestjs/common'; +import { PrismaService } from '../../infrastructure/database/prisma.service'; + +const SYSTEM_KB = { + id: 'system-builtin-kb', + userId: 'system', + title: '新手引导知识库', + description: '系统内置知识库,帮助新用户了解知习的使用方法', + status: 'active', +}; + +@Injectable() +export class SystemKnowledgeBaseSeed implements OnModuleInit { + private readonly logger = new Logger(SystemKnowledgeBaseSeed.name); + + constructor(private readonly prisma: PrismaService) {} + + async onModuleInit() { + try { + await this.prisma.knowledgeBase.upsert({ + where: { id: SYSTEM_KB.id }, + update: {}, + create: SYSTEM_KB, + }); + } catch { + this.logger.warn('Failed to seed system knowledge base'); + } + } +}