Part of DKNet.EfCore.Abstractions. Attach policy markers to the domain model and let the appropriate runtime consumer enforce them.
Use the console-project setup in the Quick Start, then replace Program.cs with this example.
using DKNet.EfCore.Abstractions.Attributes;
var property = typeof(Product).GetProperty(nameof(Product.Cost))!;
var rule = (SensitiveDataAttribute)Attribute.GetCustomAttribute(property, typeof(SensitiveDataAttribute))!;
Console.WriteLine(rule.Roles[0]); // pricing
public sealed class Product
{
[SensitiveData("pricing")]
public decimal Cost { get; set; }
}
[AuditLog] and [IgnoreAuditLog] target classes or properties; [SensitiveData] targets properties. These sealed attributes are non-inherited. They do not encrypt stored values.
| Marker | Default | Consumer effect |
|---|---|---|
[AuditLog] |
presence only | Entity opt-in under OnlyAttributedAuditedEntities; property plaintext/allow-list under the selected property policy. |
[IgnoreAuditLog] |
presence only | Exclude the entity or property from audit capture. |
[SensitiveData] |
empty IReadOnlyList<string> Roles |
Any authenticated principal may receive the property after JSON opt-in. |
[SensitiveData("pricing", "audit")] |
supplied Roles | An authenticated principal needs at least one named role. |
A null role array is normalized to an empty list. Read AuditLogs for capture policies and Encryption for protection at rest.
AuditLogs and the opted-in JSON serializer read the same SensitiveData declaration independently. Audit capture redacts unconditionally, while response serialization checks the host-supplied current principal.
IAuditedProperties. Marking a plain entity [AuditLog] does not make it an audit candidate.[IgnoreAuditLog] excludes capture. [SensitiveData] redacts even alongside [AuditLog]; declared role names do not grant plaintext audit access.