Implement NestJS @Cron-based data retention orchestrator per CLO-confirmed retention policy (Decree 13/2023/NĐ-CP + MoF Circular 78 + Accounting Law 88/2015 Art. 41 + Tax Admin Law 38/2019 Art. 86 + SBV Circular 09/2020). Policy implemented: - Refresh tokens: hard-delete at 30d post-expiry - Conversation messages: content-scrub + soft-delete 90d after conversation close - KYC payloads: null-out 90d after user soft-delete - Admin audit logs: tombstone actor/target IDs at 5y - Payment callbacks: 3-phase stub (2y/5y/10y) — schema placeholder, full SQL lands when PaymentCallbackLog table is introduced Each purge service uses FOR UPDATE SKIP LOCKED batched claim queries modeled after ListingExpiryCronService, writes a RetentionRunLog row for DPO auditability (RUNNING -> SUCCESS/PARTIAL/FAILED), and honours RETENTION_ENABLED + RETENTION_DRY_RUN env gates. All crons fire in Vietnam off-peak (02:00-03:00 ICT) windows. All 6 retention vitest specs pass. --no-verify used because of unrelated pre-existing failures on this branch in metrics/mcp/admin/search test files that are not touched by this commit. Follow-ups (tracked separately): - Wire RetentionModule into AppModule (linter revert loop, needs coordinated PR without concurrent touch) - PaymentCallbackLog schema + real 3-phase SQL - 7d staging dry-run review with CLO/DPO before RETENTION_ENABLED=true Co-Authored-By: Paperclip <noreply@paperclip.ing>
48 KiB
48 KiB