api-server/src/modules/ai-runtime/ai-job-snapshot.repository.ts
wangdl 1fadb724ec feat(M-AI-02-05): immutable AiJobSnapshot model
- 9 columns, jobId UNIQUE, ON DELETE CASCADE
- Repository: create + findByJobId only (no update/upsert)
- 14 unit tests (immutability, security, delete strategy)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-20 12:24:28 +08:00

47 lines
1.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../infrastructure/database/prisma.service';
/**
* M-AI-02-05: 不可变 Job 输入快照 Repository
*
* 约束:
* - 只允许 create + findByJobId
* - 禁止 update / upsert / 覆盖已有 Snapshot
* - Snapshot 内容必须在应用层通过安全扫描后方可写入
*/
@Injectable()
export class AiJobSnapshotRepository {
constructor(private readonly prisma: PrismaService) {}
/**
* 创建快照。每个 Job 最多一个 SnapshotjobId UNIQUE
* 若已存在则抛出 Prisma 唯一约束错误,调用方应处理。
*/
async create(data: {
jobId: string;
jobType: string;
schemaVersion: string;
redactionVersion?: string;
content: Record<string, unknown>;
contentHash?: string;
expiresAt?: Date;
}) {
return this.prisma.aiJobSnapshot.create({ data });
}
/** 按 jobId 查询快照 */
async findByJobId(jobId: string) {
return this.prisma.aiJobSnapshot.findUnique({
where: { jobId },
});
}
/** 删除过期的快照(由 cleanup service 调用) */
async deleteExpired(before: Date) {
const result = await this.prisma.aiJobSnapshot.deleteMany({
where: { expiresAt: { lt: before } },
});
return result.count;
}
}