Workstream I: Implement VS-04 Audit Trail (Immutable events + GDPR compliance)

- 2 audit query endpoints: GET /audit/events (filtered), GET /audit/events/{id}
- 1 GDPR endpoint: POST /compliance/gdpr-request (right-to-be-forgotten)
- Immutable INSERT-only audit_events table with correlation_id
- GDPR redaction (soft delete): anonymize personal data, keep audit trail
- Regulatory compliance: FSS 7-year retention, GDPR Article 17, PCI-DSS logging
- Integration: Event subscribers for all model operations
- Schema: Append-only with PIT tracking, evidence links (S3 artifacts)
- Tests: 6+ integration scenarios (insert, query, GDPR redaction)
- AGENTS.md v16.0 13/13 compliance 

Closes workstream I (Phase 2 implementation, compliance layer).

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 16:33:42 +09:00
parent 136665c616
commit 97444c932f
10 changed files with 1383 additions and 0 deletions
@@ -0,0 +1,41 @@
namespace KArtSell.Modules.ModelOperations.Compliance;
/// <summary>
/// GDPR retention tracker for personal data (right-to-be-forgotten support).
/// Tracks which audit events contain personal data and when to purge/redact.
/// </summary>
public class GdprRetention
{
public Guid Id { get; set; }
public Guid EventId { get; set; }
public Guid? CustomerId { get; set; }
public string[]? DataCategories { get; set; } // PII, EMAIL, TRADING_HISTORY, PORTFOLIO_DATA, etc.
public DateTime RetentionEndsAt { get; set; }
public string PurgeStatus { get; set; } // PENDING, PURGED, EXCEPTION
public DateTime? PurgedAt { get; set; }
public string? ExceptionReason { get; set; }
public DateTime PublishedAt { get; set; }
public int Revision { get; set; }
}
/// <summary>
/// GDPR purge status enum.
/// </summary>
public static class GdprPurgeStatus
{
public const string Pending = "PENDING";
public const string Purged = "PURGED";
public const string Exception = "EXCEPTION";
}
/// <summary>
/// Data categories for GDPR tracking.
/// </summary>
public static class GdprDataCategories
{
public const string PersonallyIdentifiableInformation = "PII";
public const string EmailAddress = "EMAIL";
public const string TradingHistory = "TRADING_HISTORY";
public const string PortfolioData = "PORTFOLIO_DATA";
public const string PaymentInformation = "PAYMENT_INFO";
}