Skip to content

Lift IEventDataMasking into JasperFx.Events.Protected, then an event data masking compliance suite #5154

Description

@jeremydmiller

Part of #5118 (compliance wave growth), epic #5110. Cross-repo: the first half targets jasperfx.

Event data masking — rewriting protected information inside already-stored events, for GDPR-style erasure — is implemented in both products with the same shape and the same member names, in parallel namespaces:

Marten Marten/Events/Protected/EventDataMasking.cs:111interface IEventDataMasking; Advanced.ApplyEventDataMasking(Action<IEventDataMasking>, ct) (AdvancedOperations.cs:837); EventGraph.AddMaskingRuleForProtectedInformation<T>(...)
Polecat Polecat/Events/Protected/EventDataMasking.cs:11interface IEventDataMasking with ForTenant(string); Advanced.ApplyEventDataMasking(...) (AdvancedOperations.cs:592); EventGraph.AddMaskingRuleForProtectedInformation<T> (EventGraph.cs:639,649)
jasperfx nothing — but JasperFx.Events/Protected/ already exists and owns StreamCompactingRequest<T>

Two independent copies of the same interface in a folder whose shared sibling already lives upstream. This is the clearest remaining upstream lift in the event store surface.

Part 1 (jasperfx): lift IEventDataMasking

Move IEventDataMasking (and the masking-rule registration on the event registry) into JasperFx.Events.Protected, with both products' current members reconciled — note Polecat's ForTenant(string tenantId) has no Marten counterpart, so decide whether it is part of the shared contract or a Polecat extension before lifting. Both products then delete their copy and re-export.

Part 2 (compliance): the suite

EventDataMaskingCompliance, needing one seam member — EventStoreComplianceFixture.ApplyEventDataMaskingAsync(Action<IEventDataMasking>), since Advanced is each product's own type — plus a config entry for the masking rules.

Marten tests today Polecat tests today
protecting_sensitive_data.cs Events/event_data_masking_tests.cs
removing_protected_information.cs
  1. A masking rule rewrites the stored event body for the matched events only
  2. Masking is idempotent — applying twice does not corrupt
  3. Masked events keep their sequence, version, timestamp and type name
  4. Masking by stream, by event type, and by a predicate over the event
  5. An inline snapshot built before masking is not silently changed (settle the intended behavior — a rebuild is the documented way to propagate)
  6. ForTenant scoping if it survives the lift as shared

Acceptance

  • jasperfx: interface lifted, JasperFxVersion bumped in the same PR, both products adopt and delete their copies
  • One fixture member + one config entry; suite enrolled in both stores
  • Originals retired in both repos

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions