Skip to content

[DEBT] Audit Encina.Marten.GDPR projections for IServiceProvider parameter anti-pattern #952

@dlrivada

Description

@dlrivada

Type

  • Failing tests
  • Missing tests
  • Code quality (warnings, analyzers)
  • Performance optimization
  • Refactoring needed
  • Documentation gap
  • Incorrect implementation
  • Other

Description

While fixing #949 (Encina.Audit.Marten projections rejecting IServiceProvider at JasperFx validation time), it became clear that the same anti-pattern may exist in other Marten integrations — specifically Encina.Marten.GDPR and Encina.Marten itself — because they all share the same architecture (event projections that need access to temporal key providers, options, and loggers).

Any EventProjection.Create(...) method in the Encina codebase that accepts IServiceProvider will fail at store boot time with the exact same InvalidProjectionException. This is a silent, critical bug: projections compile and unit tests pass (because tests pass a stub IServiceProvider directly), but the Marten store cannot be initialized in production.

Location

  • File(s): src/Encina.Marten.GDPR/**/*Projection*.cs, src/Encina.Marten/**/*Projection*.cs
  • Package(s): Encina.Marten.GDPR, Encina.Marten

Current Behavior

Unknown until audited. The following search should be run:

Get-ChildItem -Recurse src/Encina.Marten*, src/Encina.Audit.Marten -Filter *.cs `
  | Select-String -Pattern 'Task<.*>\s+Create\s*\([^)]*IServiceProvider' -Context 0,3

Any hit is a production-blocking bug identical to #949.

Expected Behavior

All Marten EventProjection.Create(...) methods accept only parameter types supported by JasperFx's projection validator:

  • CancellationToken
  • Marten.IDocumentOperations / Marten.IQuerySession
  • The event type (e.g., OrderPlacedEvent)
  • JasperFx.Events.IEvent
  • JasperFx.Events.IEvent<T>

Dependencies that would normally come from DI (loggers, options, temporal key providers) must be injected via the projection constructor, with the projection instance constructed in an IConfigureOptions<StoreOptions> implementation that resolves those dependencies from DI.

See the fix for #949 (AuditEntryProjection.cs, ConfigureMartenAuditProjections.cs) for the canonical pattern.

Root Cause

The root cause is identical to #949: IServiceProvider is not in JasperFx's allowlist of parameter types for projection methods. The JasperFx error message explicitly enumerates the supported types:

Valid options are:
  - System.Threading.CancellationToken
  - Marten.IDocumentOperations
  - <event type>
  - JasperFx.Events.IEvent
  - JasperFx.Events.IEvent<TEvent>

Until this issue is addressed, every consumer of an affected package will fail at boot.

Proposed Fix

  1. Audit all Marten projection Create signatures using the PowerShell pattern above. Document findings in this issue as a checklist of affected files.
  2. For each affected projection:
    • Move all dependencies from Create(evt, IServiceProvider) parameters into the projection constructor
    • Change the Create signature to use IDocumentOperations (and/or CancellationToken)
    • Update the corresponding IConfigureOptions<StoreOptions> implementation to construct the projection with its required dependencies
    • Update PublicAPI.Unshipped.txt
  3. Add a regression-locking unit test per affected file that invokes the real StoreOptions.Projections.Add(...) path on a plain StoreOptions instance (same pattern as [BUG] Marten audit projections unregisterable: IServiceProvider parameter rejected by JasperFx validation #949's Configure_ValidOptions_RegistersAuditProjections). This test would have caught [BUG] Marten audit projections unregisterable: IServiceProvider parameter rejected by JasperFx validation #949 on PR and must catch this class of bug going forward.
  4. Consider an architecture test in Encina.Testing.Architecture that reflects over all EventProjection subclasses in the solution and asserts no Create method takes IServiceProvider. This would prevent future regressions at compile/test time, not just per-file.

Priority

  • High — Any affected package fails at boot in production. Must ship alongside or before v0.13.4.
  • Medium
  • Low

Effort Estimate

  • Small (< 1 hour) — if the audit finds zero occurrences
  • Medium (1-4 hours) — if the audit finds 1-3 affected projections
  • Large (> 4 hours) — if the audit finds widespread usage

The audit itself is <15 minutes; the fix per occurrence is ~30-60 minutes following the established pattern from #949.

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-complianceGDPR, EU Laws, and Regulatory Compliance patternsarea-event-sourcingEvent Sourcing patterns and infrastructurearea-gdprGDPR compliance and data privacyarea-martenMarten event sourcing providercomplexity-lowComplexity: Lowmarten-integrationMarten library integrationpriority-highPriority: High (⭐⭐⭐⭐)technical-debtInternal code quality issues, refactoring, test gaps

    Projects

    Status
    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions