Feature Description
Add Encina.Audit.Marten as an additional provider for IAuditStore and IReadAuditStore, implementing event-sourced audit trails with temporal crypto-shredding via Marten (PostgreSQL).
This follows the Encina "pay-for-what-you-use" philosophy:
- Simple apps ÔÇö
InMemoryAuditStore (dev) or DB provider (production)
- Compliance-heavy apps (SOX, NIS2) ÔÇö
MartenAuditStore with immutable events + crypto-shredding
The existing IAuditStore interface does NOT change ÔÇö this is a new implementation, not a migration.
Motivation
- SOX 404: Requires immutable audit trail of internal controls. Current mutable stores allow tampering.
- NIS2 Art. 10: Requires logging with integrity guarantees. Append-only event store provides this.
- GDPR Art. 5(1)(e): Data minimization requires purging old audit data. Crypto-shredding achieves this without breaking immutability.
- Forensics: Temporal queries ("what happened at time X?") are natural with event sourcing.
Design (Option C from architectural review)
IAuditStore (unchanged interface)
|-- InMemoryAuditStore ÔÇö development/testing (existing)
|-- DB providers (13) ÔÇö production simple (existing)
+-- MartenAuditStore (NEW) ÔÇö production compliance-grade
|-- Events encrypted with temporal keys (monthly/yearly)
|-- PurgeEntriesAsync() destroys temporal keys (crypto-shredding)
|-- Marten projections for efficient querying
+-- ITemporalKeyProvider for key lifecycle management
Key Behaviors
| Operation |
DB Provider (current) |
MartenAuditStore (new) |
RecordAsync |
INSERT row |
Append encrypted event |
QueryAsync |
SELECT with filters |
Project from decrypted events |
PurgeEntriesAsync |
DELETE rows |
Destroy temporal encryption keys |
| Immutability |
Rows can be UPDATE/DELETE'd |
Events are append-only |
| Tamper evidence |
None |
Event stream integrity |
Configuration
// Simple app ÔÇö existing DB provider (no change)
services.AddEncinaAudit(options => { ... });
// Compliance-grade ÔÇö opt-in to Marten ES provider
services.AddEncinaAuditMarten(options =>
{
options.KeyRotationPeriod = TimeSpan.FromDays(365); // yearly keys
options.EncryptionScope = AuditEncryptionScope.PiiFieldsOnly;
options.RetentionPeriod = TimeSpan.FromDays(2555); // 7 years (SOX)
options.EnableAutoPurge = true;
});
Acceptance Criteria
Cross-Cutting Integration Checklist
Dependencies
Package Structure
src/
+-- Encina.Audit.Marten/
|-- MartenAuditStore.cs ÔÇö IAuditStore implementation
|-- MartenReadAuditStore.cs ÔÇö IReadAuditStore implementation
|-- Events/
| |-- AuditEntryRecorded.cs ÔÇö ES event
| +-- ReadAuditEntryRecorded.cs ÔÇö ES event
|-- Projections/
| |-- AuditEntryProjection.cs ÔÇö Read model for queries
| +-- ReadAuditProjection.cs ÔÇö Read model for read audit
|-- Crypto/
| |-- ITemporalKeyProvider.cs ÔÇö Temporal key lifecycle
| +-- TemporalKeyProvider.cs ÔÇö Marten-backed implementation
|-- ServiceCollectionExtensions.cs
|-- MartenAuditOptions.cs
+-- Diagnostics/
+-- MartenAuditDiagnostics.cs
Feature Description
Add
Encina.Audit.Martenas an additional provider forIAuditStoreandIReadAuditStore, implementing event-sourced audit trails with temporal crypto-shredding via Marten (PostgreSQL).This follows the Encina "pay-for-what-you-use" philosophy:
InMemoryAuditStore(dev) or DB provider (production)MartenAuditStorewith immutable events + crypto-shreddingThe existing
IAuditStoreinterface does NOT change ÔÇö this is a new implementation, not a migration.Motivation
Design (Option C from architectural review)
Key Behaviors
RecordAsyncQueryAsyncPurgeEntriesAsyncConfiguration
Acceptance Criteria
MartenAuditStoreimplementsIAuditStorewith event-sourced persistenceMartenReadAuditStoreimplementsIReadAuditStorewith event-sourced persistenceITemporalKeyProviderPurgeEntriesAsync()destroys temporal keys (crypto-shredding), does NOT delete eventsQueryAsyncwith filtering and paginationServiceCollectionExtensions.AddEncinaAuditMarten()registers all componentsIAuditStoreimplementations are NOT affectedIAggregateRepository<T>Cross-Cutting Integration Checklist
Dependencies
IAuditStoreinterfacePackage Structure