/** * @ai-summary Account purge job for GDPR-compliant deletion * @ai-context Processes user accounts past their 30-day grace period */ import { UserProfileRepository } from '../data/user-profile.repository'; import { pool } from '../../../core/config/database'; import { logger } from '../../../core/logging/logger'; import { auth0ManagementClient } from '../../../core/auth/auth0-management.client'; interface PurgeResult { processed: number; deleted: number; errors: Array<{ auth0Sub: string; error: string }>; } /** * Process account purges for users past the 30-day grace period * This job runs daily at 2 AM */ export async function processAccountPurges(): Promise { const repository = new UserProfileRepository(pool); const result: PurgeResult = { processed: 0, deleted: 0, errors: [], }; try { logger.info('Starting account purge job'); // Get users past grace period const usersToPurge = await repository.getUsersPastGracePeriod(); logger.info('Found users to purge', { count: usersToPurge.length }); result.processed = usersToPurge.length; // Process each user for (const user of usersToPurge) { try { logger.info('Purging user account', { auth0Sub: user.auth0Sub, email: user.email, deletionScheduledFor: user.deletionScheduledFor, }); // Hard delete from database await repository.hardDeleteUser(user.auth0Sub); // Delete from Auth0 await auth0ManagementClient.deleteUser(user.auth0Sub); result.deleted++; logger.info('User account purged successfully', { auth0Sub: user.auth0Sub, email: user.email, }); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; logger.error('Failed to purge user account', { auth0Sub: user.auth0Sub, email: user.email, error: errorMessage, }); result.errors.push({ auth0Sub: user.auth0Sub, error: errorMessage, }); } } logger.info('Account purge job completed', { processed: result.processed, deleted: result.deleted, errors: result.errors.length, }); return result; } catch (error) { logger.error('Account purge job failed', { error }); throw error; } }