/** * 审计保留与归档(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 { 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 { 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); } }