feat: Add GDPR compliance and improve UI/UX

GDPR Compliance:
- Delete CV files immediately after processing
- Add DataRetentionJob to auto-purge data after 30 days
- Add DeleteAllUserDataAsync for right to erasure
- Add Privacy Policy page with GDPR information
- Add privacy link and GDPR badge to footer

UI/UX Improvements:
- Add "Why Choose RealCV" benefits section to homepage
- Fix pricing page: Professional card highlight, consistent button styles
- Improve text contrast on dark backgrounds (0.75 → 0.85 opacity)
- Fix auth page messaging consistency
- Fix CSS --realcv-accent variable (was self-referencing)

UK Terminology:
- Change "hiring" to "recruitment" throughout
- Change "bad hires" to "poor appointments"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-22 02:00:39 +00:00
parent 2b29e19306
commit 358b0328e7
13 changed files with 483 additions and 23 deletions

View File

@@ -265,6 +265,12 @@ public sealed class ProcessCVCheckJob
cvCheckId, score);
await _auditService.LogAsync(cvCheck.UserId, AuditActions.CVProcessed, "CVCheck", cvCheckId, $"Score: {score}");
// GDPR: Delete the uploaded CV file immediately after processing
// We only need the extracted data and report, not the original file
await DeleteCVFileAsync(cvCheck.BlobUrl, cvCheckId);
cvCheck.BlobUrl = string.Empty; // Clear the URL as file no longer exists
await _dbContext.SaveChangesAsync(cancellationToken);
}
catch (Exception ex)
{
@@ -287,6 +293,29 @@ public sealed class ProcessCVCheckJob
}
}
/// <summary>
/// GDPR: Safely delete the uploaded CV file after processing.
/// </summary>
private async Task DeleteCVFileAsync(string blobUrl, Guid cvCheckId)
{
if (string.IsNullOrWhiteSpace(blobUrl))
{
_logger.LogDebug("No file to delete for CV check {CheckId}", cvCheckId);
return;
}
try
{
await _fileStorageService.DeleteAsync(blobUrl);
_logger.LogInformation("GDPR: Deleted CV file for check {CheckId}", cvCheckId);
}
catch (Exception ex)
{
// Log but don't fail the job - file deletion is important but shouldn't break processing
_logger.LogWarning(ex, "Failed to delete CV file for check {CheckId}: {BlobUrl}", cvCheckId, blobUrl);
}
}
private static (int Score, List<FlagResult> Flags) CalculateVeracityScore(
List<CompanyVerificationResult> verifications,
List<EducationVerificationResult> educationResults,