feat(1099): add ITinProtector with Data Protection encryption + last-4 helper

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-06-25 16:47:49 -07:00
parent 89238bba99
commit 5e2fbe800c
5 changed files with 64 additions and 0 deletions
+3
View File
@@ -15,6 +15,7 @@ using ROLAC.API.Json;
using ROLAC.API.Middleware;
using ROLAC.API.Services;
using ROLAC.API.Services.Logging;
using ROLAC.API.Services.Security;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
@@ -157,6 +158,8 @@ builder.Services.AddScoped<IExpenseSnapshotService, ExpenseSnapshotService>();
builder.Services.AddScoped<IMonthlyStatementService, MonthlyStatementService>();
builder.Services.AddScoped<IFinanceDashboardService, FinanceDashboardService>();
builder.Services.AddScoped<IForm990ReportService, Form990ReportService>();
builder.Services.AddDataProtection();
builder.Services.AddScoped<ITinProtector, TinProtector>();
builder.Services.AddScoped<IChurchProfileService, ChurchProfileService>();
builder.Services.AddScoped<ISettingsService, SettingsService>();
builder.Services.AddScoped<IDisbursementService, DisbursementService>();
@@ -0,0 +1,8 @@
namespace ROLAC.API.Services.Security;
/// <summary>Reversible protection for taxpayer identification numbers (SSN/EIN).</summary>
public interface ITinProtector
{
string Protect(string plaintext);
string Unprotect(string ciphertext);
}
@@ -0,0 +1,22 @@
using Microsoft.AspNetCore.DataProtection;
namespace ROLAC.API.Services.Security;
public class TinProtector : ITinProtector
{
private readonly IDataProtector _protector;
public TinProtector(IDataProtectionProvider provider)
=> _protector = provider.CreateProtector("Payee1099.Tin");
public string Protect(string plaintext) => _protector.Protect(plaintext);
public string Unprotect(string ciphertext) => _protector.Unprotect(ciphertext);
/// <summary>Last four digits of a TIN (ignoring dashes/spaces); null/empty in => null.</summary>
public static string? Last4(string? raw)
{
if (string.IsNullOrWhiteSpace(raw)) return null;
var digits = new string(raw.Where(char.IsDigit).ToArray());
return digits.Length <= 4 ? digits : digits[^4..];
}
}