Files
lingxi/apps/api/src/modules/platform/audit/audit-retention.service.ts
T
Stev_Wang 6bdda6ec62 feat(api): A5 审计采集、检索与导出
AuditInterceptor 成功 / 失败双写 audit_logs(响应前 await、脱敏、sink 缺失退化 Pino);登录 / 权限 / 客户 / 字典 / 配置等既有动作补审计;审计列表 / 详情 / 动作目录 / 异步 CSV 导出 / HMAC 签名下载;分区维护与保留归档占位;OpenAPI 快照更新。
2026-11-04 16:26:42 +08:00

56 lines
2.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.
/**
* 审计保留与归档(A5-BE-04 占位)
*
* 口径(PRD Q-08 / QT-10,最终保留期仍待产品确认):
* - `audit.retention_months` 默认 12、下限 12(不得低于 12 个月);
* - `audit_logs` 是 append-only:**本服务不执行 UPDATE / DELETE**,只提供归档骨架;
* - 真正的归档(冷存储搬迁)依赖对象存储与任务中心,A5 只登记占位;
* - 归档动作本身也应写审计(后续批次接 `audit.retention.archive`)。
*
* 当前实现只读取配置并返回计划,不会修改任何审计数据。
*/
import { Inject, Injectable, Logger } from '@nestjs/common';
import { SystemConfigService } from '../system-config/system-config.service';
export interface AuditArchivePlan {
/** 计划保留月数(来自 system_configs,下限 12) */
retentionMonths: number;
/** 该时间之前的审计可归档(只读搬迁,不删除) */
before: Date;
/** 当前仅占位:实际搬迁未启用 */
supported: false;
message: string;
}
@Injectable()
export class AuditRetentionService {
private readonly logger = new Logger('AuditRetention');
constructor(@Inject(SystemConfigService) private readonly configs: SystemConfigService) {}
/** 计算归档窗口;`before` 由调用方传入用于日志 / 任务参数 */
async archiveBefore(before: Date): Promise<AuditArchivePlan> {
const retentionMonths = await this.configs.getNumber('audit.retention_months', 12);
this.logger.warn(
`审计归档为 A5 占位:before=${before.toISOString()} retentionMonths=${String(retentionMonths)}(未执行任何删除 / 更新)`,
);
return {
retentionMonths: Math.max(12, retentionMonths),
before,
supported: false,
message:
'审计日志 append-only,归档仅做只读冷存储搬迁、不删除数据;待对象存储与任务中心就绪后接入(QT-10 保留期最终值待确认)',
};
}
/** 计划归档窗口:now - retentionMonths;供后台任务 / 运维查询 */
async plan(): Promise<AuditArchivePlan> {
const retentionMonths = await this.configs.getNumber('audit.retention_months', 12);
const months = Math.max(12, retentionMonths);
const before = new Date();
before.setMonth(before.getMonth() - months);
return this.archiveBefore(before);
}
}