namespace ROLAC.API.Entities.Logging; /// /// An append-only audit row recording a meaningful action: a data change (Create/Update/ /// Delete with before→after values), a security event (login, role/permission change), or a /// key business action (check issued, expense approved, ...). Does NOT inherit AuditableEntity. /// public class AuditLog { public long Id { get; set; } public DateTimeOffset Timestamp { get; set; } public LogLevelEnum Level { get; set; } = LogLevelEnum.Information; /// One of . public string Action { get; set; } = null!; /// One of — drives the UI grouping. public string Category { get; set; } = null!; public string? EntityName { get; set; } /// String to cover int, Guid and string primary keys uniformly. public string? EntityId { get; set; } /// JSON { "before": {...}, "after": {...} } (jsonb column); sensitive fields masked. public string? Changes { get; set; } /// Human-readable one-liner, e.g. "Check #1042 issued to Acme — $1,200.00". public string? Summary { get; set; } public string? UserId { get; set; } /// Denormalized actor email — survives user deletion and avoids a join in the grid. public string? UserEmail { get; set; } public string? IpAddress { get; set; } public string? CorrelationId { get; set; } } /// Canonical audit action names (stored verbatim in ). public static class AuditActions { public const string Create = "Create"; public const string Update = "Update"; public const string Delete = "Delete"; public const string Login = "Login"; public const string Logout = "Logout"; public const string LoginFailed = "LoginFailed"; public const string RoleChanged = "RoleChanged"; public const string PasswordChanged = "PasswordChanged"; public const string UserDeactivated = "UserDeactivated"; public const string PermissionChanged = "PermissionChanged"; public const string CheckIssued = "CheckIssued"; public const string CheckVoided = "CheckVoided"; public const string ExpenseApproved = "ExpenseApproved"; public const string StatementFinalized = "StatementFinalized"; public static readonly IReadOnlyList All = [ Create, Update, Delete, Login, Logout, LoginFailed, RoleChanged, PasswordChanged, UserDeactivated, PermissionChanged, CheckIssued, CheckVoided, ExpenseApproved, StatementFinalized, ]; } /// Top-level audit grouping (stored verbatim in ). public static class AuditCategories { public const string DataChange = "DataChange"; public const string Security = "Security"; public const string Business = "Business"; public static readonly IReadOnlyList All = [DataChange, Security, Business]; }