CHANGELOG-DETAILS
> **Milestone**: [v0.11.0 - Testing Infrastructure](https://github.com/dlrivada/Encina/milestone/8) - **COMPLETED**
[0.11.0] - 2026-01-19 - Testing Infrastructure
Milestone: v0.11.0 - Testing Infrastructure - COMPLETED
This release delivers a comprehensive testing toolkit for Encina applications, including 10 new testing packages, property-based testing support, mutation testing helpers, and CI/CD workflow templates.
Highlights
- 34 issues closed in this milestone
- 92.3% code coverage achieved (target: ≥85%)
- 0 SonarCloud issues (all addressed or excluded with justification)
- 6,500+ tests across all packages
- 10 new testing packages delivered
Table of Contents
-
- AI/LLM Patterns Issues
- Hexagonal Architecture Patterns Issues
- TDD Patterns Issues
- Developer Tooling & DX Issues
- .NET Aspire Integration Patterns Issues
- Cloud-Native Patterns Issues
- Microservices Architecture Patterns Issues
- Security Patterns Issues
- Advanced Validation Patterns Issues
- Advanced Event Sourcing Patterns Issues
- Advanced CQRS Patterns Issues
- Domain Modeling Building Blocks Issues
- Vertical Slice Architecture Patterns Issues
- Modular Monolith Architecture Patterns Issues
- Advanced Messaging Patterns Issues
- Database Providers Patterns Issues
- Advanced DDD & Workflow Patterns Issues
- Advanced EDA Patterns Issues
- Advanced Caching Patterns Issues
- Advanced Resilience Patterns Issues
- Advanced Scheduling Patterns Issues
- Advanced Observability Patterns Issues
- Web/API Integration Patterns Issues
- Advanced Testing Patterns Issues
- Advanced Distributed Lock Patterns Issues
- Message Transport Patterns Issues
- Clean Architecture Patterns Issues
Language Requirements
Encina requires C# 14 / .NET 10 or later. All packages in this framework use modern C# features including target-typed
new(),withexpressions (requiresrecordtypes), and other .NET 10 enhancements.
Added
Dogfooding Initiative (Issues #498-508) - COMPLETED
Epic initiative to refactor all Encina tests to use Encina.Testing.* infrastructure (dogfooding).
EPIC #498: Dogfooding Testing Infrastructure - CLOSED (2026-01-19)
All Phases Completed:
- Phase 1 (#499): Core package tests - CLOSED
- Phase 2 (#500): DomainModeling package tests - CLOSED
- Phase 3 (#501): Messaging package tests - CLOSED
- Phase 4 (#502): Database provider tests (ADO, Dapper, EF Core) - CLOSED
- Phase 5 (#503): Caching provider tests - CLOSED
- Phase 6 (#504): Transport provider tests - CLOSED
- Phase 7 (#505): Web Integration tests (AspNetCore, Refit, gRPC, SignalR) - CLOSED
- Phase 8 (#506): Resilience & Observability tests (Polly, OpenTelemetry) - CLOSED
- Phase 9 (#507): Validation Provider tests (FluentValidation, DataAnnotations, MiniValidator) - CLOSED
- Phase 10 (#508): Serverless & Scheduling tests (AwsLambda, AzureFunctions, Hangfire, Quartz) - CLOSED
Phase 10 Results (Serverless & Scheduling):
| Package | Tests | Improvements |
|---|---|---|
| Encina.AwsLambda.Tests | 97 | EitherAssertions, Bogus fakers |
| Encina.AzureFunctions.Tests | 124 | EitherAssertions, Bogus fakers |
| Encina.Hangfire.Tests | 29 | FakeLogger (7 skipped tests enabled), EitherAssertions |
| Encina.Hangfire.IntegrationTests | 10 | Bogus fakers |
| Encina.Quartz.Tests | 36 | Bogus fakers, EitherAssertions |
| Encina.Quartz.IntegrationTests | 9 | Bogus fakers |
| Total | 305 | Zero skipped, zero warnings |
Key Improvements (Phase 10):
- Replaced
Substitute.For<ILogger<T>>()withFakeLogger<T>for Hangfire tests (resolves Issue #6) - Enabled 7 previously skipped Hangfire logging tests using Microsoft.Extensions.Diagnostics.Testing
- Applied
ShouldBeSuccess()/ShouldBeError()EitherAssertions across all packages - Created Bogus fakers for test data generation in all 4 serverless/scheduling packages
- Added global using for
Encina.TestInfrastructure.Extensionsin all test projects
Phase 9 Coverage Results (all ≥85% target met):
| Package | Line Coverage | Branch Coverage | Tests |
|---|---|---|---|
| Encina.FluentValidation | 96.7% | 90.5% | 20 |
| Encina.DataAnnotations | 100% | 90% | 20 |
| Encina.MiniValidator | 100% | 100% | 17 |
Test Categories Implemented (Phase 9):
- Null input invariants (ArgumentNullException handling)
- Validation idempotency (same request → same result)
- Error aggregation (multiple failures captured)
- PropertyName inclusion for field-level errors
- ValidationResult invariants (IsValid/IsInvalid mutually exclusive)
- ServiceCollection extension tests (DI registration)
- Context metadata propagation (UserId, TenantId)
- Cross-provider consistency tests (13 tests verifying all providers behave identically)
Phase 8 Coverage Results (all ≥85% target met):
| Package | Coverage | Tests |
|---|---|---|
| Encina.Polly | 89.3% | 214 |
| Encina.OpenTelemetry | 92.0% | 71 |
Test Fixes Applied (Phase 8):
- Fixed
BackoffTypeTests.cs: Changedvalues.Counttovalues.Length(.NET 10 breaking change) - Fixed
BulkheadManagerTests.cs: ChangedFunc<Task>to async lambda with await for ValueTask - Fixed
AdaptiveRateLimiterGuardsTests.cs: Added async/await and fixed lambda types - Fixed
BulkheadManagerGuardsTests.cs: Fixed ValueTask handling in tests - Fixed
RateLimitingPipelineBehaviorGuardsTests.cs: ChangedSystem.Threading.RateLimitingtoEncina.Pollynamespace - Fixed
ServiceCollectionExtensionsTests.cs(OpenTelemetry): Removed incorrect assertion about options registration
Phase 7 Coverage Results (all ≥85% target met):
| Package | Coverage | Tests |
|---|---|---|
| Encina.AspNetCore | 89.3% | 101 |
| Encina.Refit | 92.1% | 46 |
| Encina.SignalR | 94.0% | 111 |
| Encina.gRPC | 97.7% | 78 |
Bug Fix: #520 - Fixed reflection bug in GrpcEncinaService.SendAsync that was searching for methods with wrong generic argument count.
Test Infrastructure Improvements:
BogusArbitrary<T>class bridging Bogus Faker with FsCheck generatorsMessageDataGeneratorswith pre-built generators for messaging entitiesTimeProviderinjection to Dapper stores for deterministic time control- Fixed SQLite datetime format incompatibility (ISO 8601 vs
datetime('now'))
Test Fixes Applied:
- ADO/Dapper GuardTests: Fixed parameter name "next" → "nextStep"
- EF Core ContractTests: Fixed invalid regex
ShouldMatch("*Type*")→ShouldContain("Type") - EF Core IntegrationTests: Added
HasConversion<string>()for SagaStatus enum - EF Core HealthCheck: Added
DefaultTagswith ["encina", "database", "efcore", "ready"]
Test Results:
- ADO.Sqlite: 209 tests ✅
- EF Core: 219 tests ✅
Solution Filters Reorganization
Note: Solution filters were subsequently deprecated after the January 2026 test consolidation. Tests are now consolidated into 7 projects under
tests/, and the full solutionEncina.slnxbuilds without issues. The.slnffiles were moved to.backup/slnf-old/.
Updated all solution filters (.slnf files) to include complete test project coverage.
Updated Filters (11 files):
Encina.Core.slnf- Added DomainModeling and all its testsEncina.Messaging.slnf- Added TestInfrastructureEncina.EventSourcing.slnf- Added TestInfrastructure, Marten.IntegrationTestsEncina.Observability.slnf- Added Messaging, TestInfrastructureEncina.Validation.slnf- Added GuardClauses.TestsEncina.Web.slnf- Added SignalR, gRPC and testsEncina.Scheduling.slnf- Reorganized TestInfrastructureEncina.Testing.slnf- Added FsCheck, Verify, Testcontainers, Architecture, Aspire (32 projects)Encina.Database.slnf- Full expansion with all 85 database provider test projectsEncina.Caching.slnf- Added TestInfrastructure, Redis.TestsEncina.Resilience.slnf- Added TestInfrastructure
New Filters Created (5 files):
Encina.Transports.slnf- RabbitMQ, Kafka, AzureServiceBus, AmazonSQS, NATS, MQTTEncina.Serverless.slnf- AwsLambda, AzureFunctionsEncina.DistributedLock.slnf- DistributedLock, Redis, SqlServerEncina.Cli.slnf- CLI toolEncina.Workflows.slnf- Workflows
Encina.Testing.Pact (New Package, Issue #436)
PactNet integration for Consumer-Driven Contract Testing (CDC) with Encina framework.
-
EncinaPactConsumerBuilder- Fluent builder for defining consumer-side Pact expectations:WithCommandExpectation<TCommand, TResponse>()- Define command request/response contractsWithQueryExpectation<TQuery, TResponse>()- Define query request/response contractsWithNotificationExpectation<TNotification>()- Define notification contractsWithCommandFailureExpectation<TCommand, TResponse>()- Define expected error responses for commandsWithQueryFailureExpectation<TQuery, TResponse>()- Define expected error responses for queriesBuildAsync()- Build the Pact and write to configured directoryGetMockServerUri()- Get mock server URI for testing
-
EncinaPactProviderVerifier- Verifies Pact contracts against provider implementation:WithProviderName()- Set the provider name for verificationWithProviderState(stateName, Action)- Register synchronous provider state setupWithProviderState(stateName, Func<Task>)- Register async provider state setupWithProviderState(stateName, Func<IDictionary<string,object>, Task>)- State setup with parametersVerifyAsync(pactFilePath)- Verify a local Pact JSON fileVerifyFromBrokerAsync(brokerUrl, providerName)- Verify from Pact Broker
-
EncinaPactFixture- xUnit test fixture for simplified test setup:- Implements
IAsyncLifetimeandIDisposablefor lifecycle management CreateConsumer(consumerName, providerName)- Create a consumer builderCreateVerifier(providerName)- Create a provider verifierVerifyAsync(consumer, Action<Uri>)- Verify with sync test actionVerifyAsync(consumer, Func<Uri, Task>)- Verify with async test actionVerifyProviderAsync(providerName)- Verify all Pact files for a providerWithEncina(encina, serviceProvider)- Configure with Encina instanceWithServices(configureServices)- Configure with DI services
- Implements
-
PactExtensions- Extension methods for working with Pact:CreatePactHttpClient(Uri)- Create HTTP client for mock serverSendCommandAsync<TCommand, TResponse>()- Send command to mock serverSendQueryAsync<TQuery, TResponse>()- Send query to mock serverPublishNotificationAsync<TNotification>()- Publish notification to mock serverReadAsEitherAsync<TResponse>()- Deserialize response as Either resultToPactResponse<TResponse>()- Convert Either to Pact-compatible response
-
Response Types:
PactSuccessResponse<T>- Success response wrapper withIsSuccessandDataPactErrorResponse- Error response withIsSuccess,ErrorCode,ErrorMessagePactVerificationResult- Verification result withSuccess,Errors,InteractionResultsInteractionVerificationResult- Individual interaction result withDescription,Success,ErrorMessage
-
Error Code Mapping - Automatic HTTP status code mapping from Encina error codes:
encina.validation.*→ 400 Bad Requestencina.authorization.*→ 403 Forbiddenencina.authentication.*→ 401 Unauthorizedencina.notfound.*→ 404 Not Foundencina.conflict.*→ 409 Conflictencina.timeout.*→ 408 Request Timeoutencina.ratelimit.*→ 429 Too Many Requests- Other errors → 500 Internal Server Error
-
Tests: 118 unit tests covering all public APIs
- EncinaPactConsumerBuilderTests (17 tests)
- EncinaPactProviderVerifierTests (24 tests)
- EncinaPactFixtureTests (23 tests)
- PactExtensionsTests (14 tests)
- GuardClauseTests (40 tests)
Encina.Testing.FsCheck (New Package, Issue #435)
FsCheck property-based testing extensions for Encina framework, compatible with FsCheck 3.x.
-
EncinaArbitraries- Pre-built arbitraries for generating Encina types:- Core types:
EncinaError(),EncinaErrorWithException(),RequestContext() - Either types:
EitherOf<T>(),SuccessEither<T>(),FailureEither<T>() - Messaging types:
OutboxMessage(),PendingOutboxMessage(),FailedOutboxMessage() InboxMessage(),SagaState(),ScheduledMessage(),RecurringScheduledMessage()
- Core types:
-
EncinaProperties- Common property validators for invariants:- Either properties:
EitherIsExclusive(),MapPreservesRightState(),BindToFailureProducesLeft() - Error properties:
ErrorHasNonEmptyMessage(),ErrorFromStringPreservesMessage() - Context properties:
ContextHasCorrelationId(),WithMetadataIsImmutable(),WithUserIdCreatesNewContext() - Outbox:
OutboxProcessedStateIsConsistent(),OutboxDeadLetterIsConsistent(),OutboxHasRequiredFields() - Inbox:
InboxProcessedStateIsConsistent(),InboxHasRequiredFields() - Saga:
SagaStatusIsValid(),SagaHasRequiredFields(),SagaCurrentStepIsNonNegative() - Scheduled:
RecurringHasCronExpression(),ScheduledHasRequiredFields() - Handler:
HandlerIsDeterministic(),AsyncHandlerIsDeterministic()
- Either properties:
-
GenExtensions- Generator extension methods:- Either generators:
ToEither(),ToSuccess(),ToFailure<T>() - Nullable generators:
OrNull(),OrNullValue() - String generators:
NonEmptyString(),AlphaNumericString(),EmailAddress() - Data generators:
JsonObject(),UtcDateTime(),PastUtcDateTime(),FutureUtcDateTime() - Other:
CronExpression(),PositiveDecimal(),ListOf(),NonEmptyListOf()
- Either generators:
-
xUnit Integration:
PropertyTestBase- Base class with auto-registered arbitrariesEncinaArbitraryProvider- Arbitrary provider for FsCheck type registration- Custom attributes:
[EncinaProperty],[QuickProperty],[ThoroughProperty] PropertyTestConfig- Configuration constants for test runs
-
Concrete Message Types for testing:
ArbitraryOutboxMessage- ImplementsIOutboxMessageArbitraryInboxMessage- ImplementsIInboxMessageArbitrarySagaState- ImplementsISagaStateArbitraryScheduledMessage- ImplementsIScheduledMessage
-
Tests: 75 unit tests covering all public APIs
- EncinaArbitrariesTests (22 tests)
- EncinaPropertiesTests (22 tests)
- GenExtensionsTests (18 tests)
- PropertyTestBaseTests (13 tests)
Encina.Testing.TUnit (New Package, Issue #171)
TUnit framework support for modern, source-generated testing with NativeAOT compatibility.
-
EncinaTUnitFixture- TUnit-compatible test fixture with fluent builder pattern:- Implements TUnit's
IAsyncInitializerandIAsyncDisposablefor lifecycle management WithConfiguration(Action<EncinaConfiguration>)- Custom Encina configurationWithServices(Action<IServiceCollection>)- Register custom services for DIWithHandlersFromAssemblyContaining<T>()- Scan assembly for handlersEncinaproperty - Get the configured Encina instanceCreateScope()- Create service scope for scoped servicesGetService<T>(),GetRequiredService<T>()- Resolve services- Fluent builder pattern with chaining support
- Proper
GC.SuppressFinalizeinDisposeAsync()per CA1816
- Implements TUnit's
-
TUnitEitherAssertions- Async-first assertions forEither<TLeft, TRight>:ShouldBeSuccessAsync()- Assert Right and return valueShouldBeSuccessAsync(expected)- Assert Right with expected valueShouldBeSuccessAsync(Func<TRight, Task>)- Assert with async validatorShouldBeErrorAsync()- Assert Left and return errorShouldBeErrorAsync(Func<TLeft, Task>)- Assert with async validatorAndReturnAsync()- Alias forShouldBeSuccessAsync()for fluent chaining
-
EncinaError-Specific Assertions:
ShouldBeErrorWithCodeAsync(code)- Assert error with specific codeShouldBeErrorContainingAsync(text)- Assert error message contains textShouldBeValidationErrorAsync()- Assert code starts with "encina.validation"ShouldBeAuthorizationErrorAsync()- Assert code starts with "encina.authorization"ShouldBeNotFoundErrorAsync()- Assert code starts with "encina.notfound"ShouldBeConflictErrorAsync()- Assert code starts with "encina.conflict"ShouldBeInternalErrorAsync()- Assert code starts with "encina.internal"
-
Task Extension Methods - All assertions work with
Task<Either<>>:task.ShouldBeSuccessAsync(),task.ShouldBeErrorAsync()task.ShouldBeValidationErrorAsync(),task.AndReturnAsync(), etc.
-
TUnitEitherCollectionAssertions- Collection assertions forIEnumerable<Either<>>:ShouldAllBeSuccessAsync()- Assert all items are Right, return valuesShouldAllBeErrorAsync()- Assert all items are Left, return errorsShouldContainSuccessAsync()- Assert at least one RightShouldContainErrorAsync()- Assert at least one LeftShouldHaveSuccessCountAsync(count)- Assert exact success countShouldHaveErrorCountAsync(count)- Assert exact error countGetSuccesses(),GetErrors()- Extract values/errors from collection
-
NativeAOT Compatibility:
- Package marked with
<IsAotCompatible>true</IsAotCompatible> - No reflection-based patterns in package code
- Compatible with TUnit's source-generated test discovery
- Package marked with
-
Tests: 56 unit tests covering all public APIs
- EncinaTUnitFixtureTests (15 tests)
- TUnitEitherAssertionsTests (21 tests)
- TUnitEitherCollectionAssertionsTests (20 tests)
-
CI/CD Workflow Templates (Issue #173) - Reusable GitHub Actions workflow templates for testing .NET 10 applications:
encina-test.yml- Basic test workflow with unit tests and coverage:- Cross-platform support (Windows, Linux, macOS)
- Configurable coverage threshold enforcement
- NuGet package caching for faster builds
- Test filter expressions for selective testing
- Integration test opt-in
encina-matrix.yml- Matrix testing across OS and database providers:- Multiple OS testing (Windows, Linux, macOS)
- Database service containers (PostgreSQL, SQL Server, MySQL, Redis, MongoDB, SQLite)
- Parallel execution with configurable max-parallel
- Automatic connection string configuration
- Summary report across all matrix combinations
encina-full-ci.yml- Complete CI pipeline with all stages:- Build & analyze (formatting, warnings-as-errors)
- Unit tests with coverage threshold
- Integration tests with Docker services (optional)
- Architecture tests (optional)
- Mutation tests with Stryker (optional)
- NuGet package creation and publishing
- CI summary report
- Documentation:
docs/ci-cd-templates.mdwith usage examples and best practices - Tests:
Encina.Workflows.Testsproject with 49 YAML validation tests
-
Encina.Testing Package - Enhanced testing fixtures for fluent test setup (Issue #444):
EncinaTestFixture- Fluent builder pattern for test setup:WithMockedOutbox(),WithMockedInbox(),WithMockedSaga()- Configure fake storesWithMockedScheduling(),WithMockedDeadLetter()- Additional store mockingWithAllMockedStores()- Enable all mocked stores at onceWithHandler<THandler>()- Register request/notification handlersWithService<TService>(instance)- Register custom service instancesWithService<TService, TImplementation>()- Register service with implementation typeWithConfiguration(Action<EncinaConfiguration>)- Custom Encina configurationSendAsync<TResponse>(IRequest<TResponse>)- Send request and get test contextPublishAsync(INotification)- Publish notification and get test context- Properties:
Outbox,Inbox,SagaStore,ScheduledMessageStore,DeadLetterStore ClearStores()- Reset all stores for test isolationIAsyncLifetimesupport for xUnit integration
EncinaTestContext<TResponse>- Chainable assertion context:ShouldSucceed(),ShouldFail()- Assert result stateShouldSucceedWith(Action<TResponse>)- Assert and verify success valueShouldFailWith(Action<EncinaError>)- Assert and verify errorShouldSatisfy(Action<TResponse>)- Custom verificationOutboxShouldContain<TNotification>()- Verify outbox messagesOutboxShouldBeEmpty(),OutboxShouldContainExactly(count)- Outbox assertionsSagaShouldBeStarted<TSaga>()- Verify saga lifecycleSagaShouldHaveTimedOut<TSaga>(),SagaShouldHaveCompleted<TSaga>()- Saga state assertionsSagaShouldBeCompensating<TSaga>(),SagaShouldHaveFailed<TSaga>()- Saga failure assertionsGetSuccessValue(),GetErrorValue()- Extract valuesAndproperty for fluent chaining- Implicit conversion to
Either<EncinaError, TResponse>
- Time-Travel Testing (Phase 3):
WithFakeTimeProvider(),WithFakeTimeProvider(DateTimeOffset)- Configure fake timeAdvanceTimeBy(TimeSpan),AdvanceTimeByMinutes(int),AdvanceTimeByHours(int)- Advance timeAdvanceTimeByDays(int),SetTimeTo(DateTimeOffset),GetCurrentTime()- Time controlThenAdvanceTimeBy(),ThenAdvanceTimeByHours()- Context chaining for time-travelTimeProviderproperty for direct FakeTimeProvider access
- Messaging Pattern Test Helpers (Issue #169) - BDD Given/When/Then helpers for messaging patterns:
OutboxTestHelper- Fluent test helper for outbox pattern testing:GivenEmptyOutbox(),GivenMessages(),GivenPendingMessage(),GivenProcessedMessage(),GivenFailedMessage()- Setup methodsWhenMessageAdded(),WhenMessageProcessed(),WhenMessageFailed(),When(),WhenAsync()- Action methodsThenMessageWasAdded<T>(),ThenOutboxContains<T>(),ThenMessageWasProcessed(),ThenNoMessagesWereAdded(),ThenNoException(),ThenThrows<T>()- Assertion methods- Time-travel:
AdvanceTimeBy(),AdvanceTimeByMinutes(),AdvanceTimeByHours(),AdvanceTimeByDays(),GetCurrentTime()
InboxTestHelper- Fluent test helper for inbox/idempotency testing:GivenEmptyInbox(),GivenNewMessage(),GivenProcessedMessage(),GivenFailedMessage()- Setup methodsWhenMessageReceived(),WhenMessageRegistered(),WhenMessageProcessed(),WhenMessageFailed(),When(),WhenAsync()- Action methodsThenMessageWasRegistered(),ThenMessageIsProcessed(),ThenCachedResponseIs<T>(),ThenMessageWasDuplicate(),ThenNoException(),ThenThrows<T>()- Assertion methods
SagaTestHelper- Fluent test helper for saga orchestration testing:GivenNoSagas(),GivenNewSaga<TSaga, TData>(),GivenRunningSaga<TSaga, TData>(),GivenCompletedSaga(),GivenFailedSaga(),GivenTimedOutSaga()- Setup methodsWhenSagaStarts<TSaga, TData>(),WhenSagaAdvancesToNextStep(),WhenSagaDataUpdated<TData>(),WhenSagaCompletes(),WhenSagaStartsCompensating(),WhenSagaFails(),WhenSagaTimesOut()- Action methodsThenSagaWasStarted<TSaga>(),ThenSagaIsAtStep(),ThenSagaIsCompleted(),ThenSagaIsFailed(),ThenSagaIsCompensating(),ThenSagaData<TData>(),ThenNoException(),ThenThrows<T>()- Assertion methods
SchedulingTestHelper- Fluent test helper for scheduled message testing:GivenNoScheduledMessages(),GivenScheduledMessage(),GivenRecurringMessage(),GivenDueMessage(),GivenProcessedMessage(),GivenFailedMessage(),GivenCancelledMessage()- Setup methodsWhenMessageScheduled(),WhenRecurringMessageScheduled(),WhenMessageProcessed(),WhenMessageFailed(),WhenMessageCancelled(),WhenMessageRescheduled()- Action methodsThenMessageWasScheduled<T>(),ThenMessageIsDue<T>(),ThenMessageIsNotDue(),ThenMessageWasProcessed(),ThenMessageWasCancelled(),ThenMessageIsRecurring(),ThenMessageHasCron(),ThenScheduledMessageCount()- Assertion methods- Time-travel:
AdvanceTimeBy(),AdvanceTimeByMinutes(),AdvanceTimeByHours(),AdvanceTimeByDays(),AdvanceTimeUntilDue(),GetCurrentTime(),GetDueMessagesAsync()
- (NEW Issue #170) Improved Assertions with Shouldly-like fluent chaining (xUnit-based):
AndConstraint<T>- Fluent chaining pattern for assertions:Valueproperty for accessing the asserted valueAndproperty for continuing assertion chainsShouldSatisfy(Action<T>)for custom assertions- Implicit conversion to underlying value type
EitherAssertionsenhancements:ShouldBeSuccessAnd(),ShouldBeRightAnd()returningAndConstraint<TRight>ShouldBeErrorAnd(),ShouldBeLeftAnd()returningAndConstraint<TLeft>ShouldBeValidationErrorForProperty(),ShouldBeValidationErrorForPropertyAnd()for property-specific validation- EncinaError
*Andvariants:ShouldBeErrorWithCodeAnd(),ShouldBeValidationErrorAnd(),ShouldBeAuthorizationErrorAnd(),ShouldBeNotFoundErrorAnd(),ShouldBeErrorContainingAnd() - Async
*Andvariants:ShouldBeSuccessAndAsync(),ShouldBeErrorAndAsync(),ShouldBeValidationErrorAndAsync(), etc.
EitherCollectionAssertions- Collection assertions forIEnumerable<Either<TLeft, TRight>>:ShouldAllBeSuccess(),ShouldAllBeSuccessAnd()for all-success verificationShouldAllBeError(),ShouldAllBeErrorAnd()for all-error verificationShouldContainSuccess(),ShouldContainSuccessAnd(),ShouldContainError(),ShouldContainErrorAnd()ShouldHaveSuccessCount(),ShouldHaveSuccessCountAnd(),ShouldHaveErrorCount(),ShouldHaveErrorCountAnd()- EncinaError-specific:
ShouldContainValidationErrorFor(),ShouldNotContainAuthorizationErrors(),ShouldContainAuthorizationError(),ShouldAllHaveErrorCode() - Async variants:
ShouldAllBeSuccessAsync(),ShouldAllBeErrorAsync(),ShouldContainSuccessAsync(),ShouldContainErrorAsync() - Helper methods:
GetSuccesses(),GetErrors()
StreamingAssertions-IAsyncEnumerable<Either<TLeft, TRight>>assertions:ShouldAllBeSuccessAsync(),ShouldAllBeSuccessAndAsync(),ShouldAllBeErrorAsync(),ShouldAllBeErrorAndAsync()ShouldContainSuccessAsync(),ShouldContainSuccessAndAsync(),ShouldContainErrorAsync(),ShouldContainErrorAndAsync()ShouldHaveCountAsync(),ShouldHaveSuccessCountAsync(),ShouldHaveErrorCountAsync()FirstShouldBeSuccessAsync(),FirstShouldBeErrorAsync()for first-item assertionsShouldBeEmptyAsync(),ShouldNotBeEmptyAsync()for stream emptiness- EncinaError-specific:
ShouldContainValidationErrorForAsync(),ShouldNotContainAuthorizationErrorsAsync(),ShouldContainAuthorizationErrorAsync(),ShouldAllHaveErrorCodeAsync() - Helper:
CollectAsync()to materialize async streams
- (NEW Issue #434) BDD Handler and Saga Specification Testing:
HandlerSpecification<TRequest, TResponse>- Abstract base class for handler BDD testing:Given(Action<TRequest>)- Setup request modificationsGivenRequest(TRequest)- Setup explicit requestWhen(Action<TRequest>),WhenAsync(Action<TRequest>, CancellationToken)- Execute handlerThenSuccess(Action<TResponse>?)- Assert success and validateThenSuccessAnd()- Assert success returningAndConstraint<TResponse>ThenError(Action<EncinaError>?)- Assert error and validateThenErrorAnd()- Assert error returningAndConstraint<EncinaError>ThenValidationError(params string[])- Assert validation error for propertiesThenValidationErrorAnd(params string[])- ReturnsAndConstraint<EncinaError>ThenErrorWithCode(string)- Assert specific error codeThenErrorWithCodeAnd(string)- ReturnsAndConstraint<EncinaError>ThenThrows<TException>()- Assert exception thrownThenThrowsAnd<TException>()- ReturnsAndConstraint<TException>
Scenario<TRequest, TResponse>- Fluent inline scenario builder:Describe(string)- Create named scenarioGiven(Action<TRequest>)- Setup request modificationsUsingHandler(Func<IRequestHandler<TRequest, TResponse>>)- Set handler factoryWhenAsync(TRequest, CancellationToken)- Execute and returnScenarioResult<TResponse>
ScenarioResult<TResponse>- Result wrapper with assertions:IsSuccess,HasException,Result,ExceptionpropertiesShouldBeSuccess(Action<TResponse>?)- Assert successShouldBeSuccessAnd()- ReturnsAndConstraint<TResponse>ShouldBeError(Action<EncinaError>?)- Assert errorShouldBeErrorAnd()- ReturnsAndConstraint<EncinaError>ShouldBeValidationError(params string[])- Assert validation errorShouldBeErrorWithCode(string)- Assert specific error codeShouldThrow<TException>()- Assert exceptionShouldThrowAnd<TException>()- ReturnsAndConstraint<TException>- Implicit conversion to
Either<EncinaError, TResponse>
SagaSpecification<TSaga, TSagaData>- Abstract base class for saga BDD testing:GivenData(Action<TSagaData>)- Setup saga data modificationsGivenSagaData(TSagaData)- Setup explicit saga dataWhenComplete(CancellationToken)- Execute saga from step 0WhenStep(int, CancellationToken)- Execute saga from specific stepWhenCompensate(int, CancellationToken)- Execute compensationThenSuccess(Action<TSagaData>?)- Assert saga successThenSuccessAnd()- ReturnsAndConstraint<TSagaData>ThenError(Action<EncinaError>?)- Assert saga errorThenErrorAnd()- ReturnsAndConstraint<EncinaError>ThenErrorWithCode(string)- Assert specific error codeThenThrows<TException>()- Assert exceptionThenThrowsAnd<TException>()- ReturnsAndConstraint<TException>ThenCompleted()- Assert saga completed successfullyThenCompensated()- Assert compensation executedThenFailed(string?)- Assert saga failed with optional messageThenData(Action<TSagaData>)- Validate saga data state
- (NEW Issue #362) Module Testing Utilities for modular monolith testing:
ModuleTestFixture<TModule>- Fluent test fixture for isolated module testing:WithMockedModule<TModuleApi>(Action<MockModuleApi<TModuleApi>>)- Mock dependent module with fluent setupWithMockedModule<TModuleApi>(TModuleApi)- Mock dependent module with implementationWithFakeModule<TModuleApi, TFakeModule>()- Register fake module implementationWithFakeModule<TModuleApi, TFakeModule>(TFakeModule)- Register fake module instanceWithService<TService>(TService),WithService<TService, TImplementation>()- Service registrationConfigureServices(Action<IServiceCollection>)- Custom service configurationWithMockedOutbox(),WithMockedInbox(),WithMockedSaga()- Messaging store mockingWithMockedScheduling(),WithMockedDeadLetter(),WithAllMockedStores()- Additional storesWithFakeTimeProvider(),WithFakeTimeProvider(DateTimeOffset)- Time controlAdvanceTimeBy(TimeSpan)- Time advancementConfigure(Action<EncinaConfiguration>)- Encina configurationSendAsync<TResponse>(IRequest<TResponse>)- Send request returningModuleTestContextPublishAsync(INotification)- Publish notification capturing integration events- Properties:
Module,IntegrationEvents,Outbox,Inbox,SagaStore,ScheduledMessageStore,DeadLetterStore,TimeProvider,ServiceProvider ClearStores()- Reset all stores and captured eventsIDisposableandIAsyncDisposablesupport
ModuleTestContext<TResponse>- Fluent assertion context for module test results:ShouldSucceed(),ShouldFail()- Basic result assertionsShouldSucceedWith(Action<TResponse>),ShouldFailWith(Action<EncinaError>)- With validationShouldSucceedAnd(),ShouldFailAnd()- ReturnAndConstraint<T>for chainingShouldFailWithMessage(string)- Assert error contains messageShouldBeValidationError()- Assert validation errorOutboxShouldContain<T>(),OutboxShouldBeEmpty(),OutboxShouldHaveCount(int)- Outbox assertionsIntegrationEventShouldContain<T>(),IntegrationEventsShouldBeEmpty()- Integration event assertions- Properties:
Fixture,Result,IsSuccess,Value,Error
IntegrationEventCollector- Thread-safe collection for integration event assertions:Add(INotification)(internal) - Capture eventsClear()- Clear captured eventsGetEvents<TEvent>(),GetFirst<TEvent>(),GetFirstOrDefault<TEvent>(),GetSingle<TEvent>()- Query eventsContains<TEvent>(),Contains<TEvent>(Func<TEvent, bool>)- Check existenceShouldContain<TEvent>(),ShouldContain<TEvent>(Func<TEvent, bool>)- Fluent assertionsShouldContainAnd<TEvent>(),ShouldContainSingle<TEvent>(),ShouldContainSingleAnd<TEvent>()- With chainingShouldNotContain<TEvent>(),ShouldBeEmpty(),ShouldHaveCount(int),ShouldHaveCount<TEvent>(int)- Additional assertions
MockModuleApi<TModuleApi>- Simple mock builder for module APIs using DispatchProxy:Setup(string methodName, Delegate)- Configure method implementationSetupProperty(string propertyName, object?)- Configure property valueBuild()- Create proxy instance implementing the interface
ModuleArchitectureRules- Pre-built ArchUnitNET rules for modules:ModulesShouldBeSealed()- Module implementations should be sealedIntegrationEventsShouldBeSealed()- Integration events should be sealedDomainShouldNotDependOnInfrastructure(string domainNs, string infraNs)- Layer dependency rule
ModuleArchitectureAnalyzer- Module dependency analysis:Analyze(params Assembly[])- Analyze assembliesAnalyzeAssemblyContaining<T1>(),AnalyzeAssemblyContaining<T1, T2>()- Type-based analysisResultproperty returningModuleAnalysisResultArchitectureproperty for ArchUnitNET access
ModuleAnalysisResult- Analysis result with assertions:Modules,Dependencies,CircularDependenciespropertiesModuleCount,HasCircularDependenciespropertiesShouldHaveNoCircularDependencies()- Assert no cyclesShouldContainModule(string)- Assert module existsShouldHaveDependency(string source, string target)- Assert dependency existsShouldNotHaveDependency(string source, string target)- Assert no dependency
- Supporting records:
ModuleInfo,ModuleDependency,CircularDependency DependencyTypeenum:Direct,PublicApi,IntegrationEvent
- (NEW Issue #172) Mutation Testing Helper Attributes (
Encina.Testing.Mutationsnamespace):NeedsMutationCoverageAttribute- Mark tests needing stronger assertions:Reason(required) - Description of mutation coverage gapMutantId(optional) - Stryker mutant ID from reportSourceFile(optional) - Path to source file with surviving mutantLine(optional) - Line number where mutation was applied[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]- Multiple instances per test allowed
MutationKillerAttribute- Document tests that kill specific mutations:MutationType(required) - Type of mutation killed (e.g., "EqualityMutation", "ArithmeticMutation")Description(optional) - Detailed description of what mutation is killedSourceFile(optional) - Path to source file containing the mutation targetTargetMethod(optional) - Method name where mutation appliesLine(optional) - Line number where mutation applies[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]- Multiple instances per test allowed
- (FIX Issue #497) ModuleArchitectureAnalyzerTests: Fix false positive dependency detection:
- Root Cause: Test modules (
OrdersModule,PaymentsModule,ShippingModule) were in the same namespace, causing the analyzer to detect false dependencies - Solution: Moved test modules to distinct namespaces (
Encina.Testing.Tests.Modules.TestModules.Orders, etc.) to simulate real modular architecture - Additional Fix: Adjusted
Result_DiscoversModulesInAssemblytest to verify module containment rather than exact match (assembly may contain additional test modules from other files) - Common mutation types:
EqualityMutation,ArithmeticMutation,BooleanMutation,UnaryMutation,NullCheckMutation,StringMutation,LinqMutation,BlockRemoval - Documentation updated in
docs/en/guides/MUTATION_TESTING.md
- Root Cause: Test modules (
-
Encina.Testing.Testcontainers Package - Docker container fixtures for integration tests (Issues #162, #163):
SqlServerContainerFixture- SQL Server container (mcr.microsoft.com/mssql/server:2022-latest)PostgreSqlContainerFixture- PostgreSQL container (postgres:17-alpine)MySqlContainerFixture- MySQL container (mysql:9.1)MongoDbContainerFixture- MongoDB container (mongo:7)RedisContainerFixture- Redis container (redis:7-alpine)ConfiguredContainerFixture<TContainer>- Generic fixture for custom-configured containersEncinaContainers- Static factory class for creating container fixtures:SqlServer(),PostgreSql(),MySql(),MongoDb(),Redis()- Default configurations- Overloads accepting
Action<TBuilder>for custom container configuration
- All fixtures implement
IAsyncLifetimefor xUnit integration - Properties:
Container,ConnectionString,IsRunning - Automatic cleanup with
WithCleanUp(true) - Respawn Integration (Issue #163):
DatabaseIntegrationTestBase<TFixture>- Abstract base class combining Testcontainers with RespawnSqlServerIntegrationTestBase- Pre-configured base class for SQL Server integration testsPostgreSqlIntegrationTestBase- Pre-configured base class for PostgreSQL integration testsMySqlIntegrationTestBase- Pre-configured base class for MySQL integration tests- Automatic database reset before each test via Respawn
- Customizable
RespawnOptionsthrough property override ResetDatabaseAsync()method for mid-test cleanup- Default exclusion of Encina messaging tables from cleanup
-
Encina.Testing.Architecture Package - Architecture testing rules using ArchUnitNET (Issue #432, Phase 6 of #444):
EncinaArchitectureRules- Static class with pre-built architecture rules:HandlersShouldNotDependOnInfrastructure()- Handlers should use abstractionsHandlersShouldBeSealed()- Handler classes should be sealedNotificationsShouldBeSealed()- Notifications and events should be sealedBehaviorsShouldBeSealed()- Pipeline behaviors should be sealedValidatorsShouldFollowNamingConvention()- Validators should end with "Validator"DomainShouldNotDependOnMessaging(namespace)- Domain layer isolationDomainShouldNotDependOnApplication(domain, app)- Domain independenceApplicationShouldNotDependOnInfrastructure(app, infra)- Layer separationCleanArchitectureLayersShouldBeSeparated(domain, app, infra)- Combined layer rulesRepositoryInterfacesShouldResideInDomain(namespace)- Repository interface locationRepositoryImplementationsShouldResideInInfrastructure(namespace)- Impl location- (NEW Phase 6)
RequestsShouldFollowNamingConvention()- Requests should end with Command/Query - (NEW Phase 6)
AggregatesShouldFollowPattern(namespace)- Aggregates should be sealed - (NEW Phase 6)
ValueObjectsShouldBeSealed()- Value objects should be sealed - (NEW Phase 6)
SagasShouldBeSealed()- Sagas should be sealed - (NEW Phase 6)
StoreImplementationsShouldBeSealed()- Store impls should be sealed - (NEW Phase 6)
EventHandlersShouldBeSealed()- Event handlers should be sealed - (NEW Issue #166)
HandlersShouldImplementCorrectInterface()- Handlers must implement IRequestHandler, ICommandHandler, IQueryHandler, or INotificationHandler - (NEW Issue #166)
CommandsShouldImplementICommand()- Commands must implement ICommand<TResponse> or ICommand - (NEW Issue #166)
QueriesShouldImplementIQuery()- Queries must implement IQuery<TResponse> or IQuery - (NEW Issue #166)
HandlersShouldNotDependOnControllers()- Handlers must not depend on presentation layer - (NEW Issue #166)
PipelineBehaviorsShouldImplementCorrectInterface()- Behaviors must implement IPipelineBehavior<,> - (NEW Issue #166)
SagaDataShouldBeSealed()- Saga data classes must be sealed for serialization
EncinaArchitectureTestBase- Abstract test class with pre-defined tests:- Override
ApplicationAssembly,DomainAssembly,InfrastructureAssembly - Override namespace properties for layer separation rules
- Pre-built test methods:
HandlersShouldNotDependOnInfrastructure(), etc. - (NEW Issue #166)
HandlersShouldImplementCorrectInterface()- Test handler interfaces - (NEW Issue #166)
CommandsShouldImplementICommand()- Test command interfaces - (NEW Issue #166)
QueriesShouldImplementIQuery()- Test query interfaces - (NEW Issue #166)
HandlersShouldNotDependOnControllers()- Test handler-controller separation - (NEW Issue #166)
PipelineBehaviorsShouldImplementCorrectInterface()- Test behavior interfaces - (NEW Issue #166)
SagaDataShouldBeSealed()- Test saga data sealing
- Override
EncinaArchitectureRulesBuilder- Fluent builder for custom rule composition:- Chain multiple rules with fluent API
Verify()- ThrowsArchitectureRuleExceptionon violationsVerifyWithResult()- ReturnsArchitectureVerificationResultwithout throwingApplyAllStandardRules()- Apply all standard Encina rules at once (excludes saga rules)- (NEW)
ApplyAllSagaRules()- Apply saga-specific rules (opt-in) AddCustomRule(IArchRule)- Add custom ArchUnitNET rules- (NEW Phase 6)
EnforceRequestNaming()- Enforce request naming conventions - (NEW Phase 6)
EnforceSealedAggregates(namespace)- Enforce sealed aggregates - (NEW Phase 6)
EnforceSealedValueObjects()- Enforce sealed value objects - (NEW Phase 6)
EnforceSealedSagas()- Enforce sealed sagas - (NEW Phase 6)
EnforceSealedEventHandlers()- Enforce sealed event handlers - (NEW Issue #166)
EnforceHandlerInterfaces()- Enforce handler interface implementation - (NEW Issue #166)
EnforceCommandInterfaces()- Enforce command interface implementation - (NEW Issue #166)
EnforceQueryInterfaces()- Enforce query interface implementation - (NEW Issue #166)
EnforceHandlerControllerIsolation()- Enforce handler-controller separation - (NEW Issue #166)
EnforcePipelineBehaviorInterfaces()- Enforce behavior interface implementation - (NEW Issue #166)
EnforceSealedSagaData()- Enforce sealed saga data classes
ArchitectureRuleViolation- Record for rule violation detailsArchitectureVerificationResult- Result withIsSuccess,IsFailure,ViolationsArchitectureRuleException- Exception with formatted violation messages
-
Encina.Testing.Verify Package - Snapshot testing integration with Verify (Issue #430):
EncinaVerifySettings- Configuration for Verify with Encina-specific scrubbers:Initialize()- Configures scrubbers and converters (idempotent)- Automatic scrubbing of UTC timestamps (CreatedAtUtc, ProcessedAtUtc, etc.)
- Automatic scrubbing of ISO 8601 timestamps in content
- Stack trace removal from error messages
- Custom EncinaError converter for clean output
EncinaVerify- Static helper methods for snapshot preparation:PrepareEither<TLeft, TRight>()- Prepare Either results (shows IsRight, Value/Error)ExtractSuccess<TResponse>()- Extract success value or throwExtractError<TResponse>()- Extract error or throwPrepareUncommittedEvents()- Prepare aggregate events with metadataPrepareOutboxMessages()- Prepare outbox messages for verificationPrepareInboxMessages()- Prepare inbox messages for verificationPrepareSagaState()- Prepare saga state for verificationPrepareScheduledMessages()- Prepare scheduled messages for verificationPrepareDeadLetterMessages()- Prepare dead letter messages for verification- (NEW Phase 5)
PrepareHandlerResult<TRequest, TResponse>()- Prepare handler result with request context - (NEW Phase 5)
PrepareSagaStates()- Prepare multiple saga states for verification - (NEW Phase 5)
PrepareValidationError()- Prepare validation error for verification - (NEW Phase 5)
PrepareTestScenario<TResponse>()- Prepare complete test scenario with outbox/sagas
- (NEW Phase 5)
EncinaTestContextExtensions- Extension methods for Either results:ForVerify<TResponse>()- Prepare Either for snapshot verificationSuccessForVerify<TResponse>()- Extract success value for verificationErrorForVerify<TResponse>()- Extract error for verification
- Automatic GUID scrubbing with deterministic placeholders (Guid_1, Guid_2, etc.)
- Integration with Verify.Xunit for xUnit test framework
-
Encina.Aspire.Testing Package - Aspire integration testing support (Issue #418):
WithEncinaTestSupport()- Extension forDistributedApplicationTestingBuilder:- Registers fake stores for testing (outbox, inbox, saga, scheduled, dead letter)
- Configurable data cleanup before each test
- Customizable wait timeouts and polling intervals
EncinaTestSupportOptions- Configuration for test behavior:ClearOutboxBeforeTest,ClearInboxBeforeTest,ResetSagasBeforeTestClearScheduledMessagesBeforeTest,ClearDeadLetterBeforeTestDefaultWaitTimeout,PollingInterval
EncinaTestContext- Centralized access to test state and operations:- Direct access to fake stores for inspection
ClearAll(),ClearOutbox(),ClearInbox(),ClearSagas()methods
- Assertion extensions for messaging patterns:
AssertOutboxContainsAsync<T>()- Verify outbox contains notification typeAssertInboxProcessedAsync()- Verify inbox message was processedAssertSagaCompletedAsync<T>(),AssertSagaCompensatedAsync<T>()- Verify saga lifecycleAssertDeadLetterContainsAsync<T>()- Verify dead letter contains message type
- Wait helpers for async operations:
WaitForOutboxProcessingAsync()- Wait for all outbox messages to be processedWaitForSagaCompletionAsync<T>()- Wait for specific saga to complete
- Inspection helpers:
GetPendingOutboxMessages(),GetRunningSagas<T>(),GetDeadLetterMessages()GetEncinaTestContext(),GetOutboxStore(),GetSagaStore()
- Failure simulation for resilience testing:
SimulateSagaTimeout(),SimulateSagaFailure()- Saga failure scenariosSimulateOutboxMessageFailure(),SimulateOutboxDeadLetter()- Outbox failuresSimulateInboxMessageFailure(),SimulateInboxExpiration()- Inbox failuresAddToDeadLetterAsync()- Directly add messages to dead letter store
-
Encina.Testing.Respawn Package - Intelligent database cleanup for integration tests (Issue #427):
DatabaseRespawner- Abstract base class for provider-specific respawnersSqlServerRespawner- SQL Server implementation using Respawn libraryPostgreSqlRespawner- PostgreSQL implementation using Respawn libraryMySqlRespawner- MySQL/MariaDB implementation using Respawn librarySqliteRespawner- Custom SQLite implementation (Respawn doesn't support SQLite natively)RespawnOptions- Configuration for table filtering, schema control, and Encina messaging tablesRespawnerFactory- Factory for creating respawners with automatic provider detectionRespawnAdapter- Enum for supported database adapters (SqlServer, PostgreSql, MySql, Oracle)- Features:
- Foreign key-aware reset (deletes in correct dependency order)
TablesToIgnore- Exclude specific tables from cleanupSchemasToInclude/SchemasToExclude- Schema filteringResetEncinaMessagingTables- Option to preserve Outbox/Inbox/Saga tables (default: true)WithReseed- Reset identity columns (default: true)CheckTemporalTables- Handle SQL Server temporal tablesInferAdapter()- Automatically detect database provider from connection string- Builder pattern support via
FromBuilder()method
- Async initialization with
InitializeAsync()for lazy respawner setup GetDeleteCommands()for debugging and verification
-
Encina.Testing.Bogus Package - Realistic test data generation with Bogus (Issue #431):
EncinaFaker<T>- Base faker class for Encina requests with reproducibility:- Default seed (12345) for deterministic test data
UseSeed(),WithLocale(),StrictMode()configuration methods- Fluent API for custom rules
OutboxMessageFaker- Generate outbox messages for testing:- Default pending state with random notification types
AsProcessed()- Generate processed messagesAsFailed(retryCount)- Generate failed messages with error infoWithNotificationType(),WithContent()customization
InboxMessageFaker- Generate inbox messages for idempotency testing:AsProcessed(response)- Generate processed with cached responseAsFailed(retryCount)- Generate failed messagesAsExpired()- Generate expired messages for cleanup testsWithMessageId(),WithRequestType()customization
SagaStateFaker- Generate saga states for orchestration testing:AsCompleted(),AsCompensating(),AsFailed(),AsTimedOut()lifecycle statesWithSagaType(),WithSagaId(),WithData(),AtStep()customization
ScheduledMessageFaker- Generate scheduled messages:AsDue()- Generate messages ready for executionAsRecurring(cron)- Generate recurring messages with cron expressionAsRecurringExecuted()- Generate recurring with last executionScheduledAt(),WithRequestType(),WithContent()customization
- Extension methods for common Encina patterns:
- Identifiers:
CorrelationId(),UserId(),TenantId(),IdempotencyKey() - Types:
NotificationType(),RequestType(),SagaType(),SagaStatus() - UTC dates:
RecentUtc(),SoonUtc() - JSON:
JsonContent(propertyCount)
- Identifiers:
- Fake implementations:
FakeOutboxMessage,FakeInboxMessage,FakeSagaState,FakeScheduledMessage - Domain Model Faker Extensions (Issue #161) - Extension methods for DDD patterns:
- Entity ID generation (
Randomizerextensions):EntityId<TId>()- Generic type-switched entity ID generation (Guid, int, long, string)GuidEntityId()- Generate non-empty GUID identifiersIntEntityId(min, max)- Generate positive integer IDs (min >= 1)LongEntityId(min, max)- Generate positive long IDs (min >= 1)StringEntityId(length, prefix)- Generate alphanumeric IDs with optional prefix
- Strongly-typed ID value generation (
Randomizerextensions):StronglyTypedIdValue<TValue>()- Generic value generation for StronglyTypedIdGuidStronglyTypedIdValue()- Non-empty GUID for StronglyTypedId<Guid>IntStronglyTypedIdValue(min, max)- Positive int for StronglyTypedId<int>LongStronglyTypedIdValue(min, max)- Positive long for StronglyTypedId<long>StringStronglyTypedIdValue(length, prefix)- Alphanumeric for StronglyTypedId<string>
- Value object generation (
RandomizerandDateextensions):QuantityValue(min, max)- Non-negative integers (default: 0-1000)PercentageValue(min, max, decimals)- Decimal percentage 0-100 with precisionDateRangeValue(daysInPast, daysSpan)- (DateOnly Start, DateOnly End) tupleTimeRangeValue(minHourSpan, maxHourSpan)- (TimeOnly Start, TimeOnly End) tuple
- Seed reproducibility for all domain model methods:
- All ID and value methods are fully reproducible with seed alone
- Date/time methods (
DateRangeValue,TimeRangeValue) are reproducible relative to the current base date/time (i.e., seed + current UTC date/time)
- Entity ID generation (
-
Encina.Testing.WireMock Package - HTTP API mocking for integration tests (Issues #428, #164):
EncinaWireMockFixture- xUnit fixture for in-process WireMock server with fluent API:- HTTP method stubs:
StubGet(),StubPost(),StubPut(),StubPatch(),StubDelete() - Advanced stubbing:
Stub()with request configuration,StubSequence()for sequential responses - Fault simulation:
StubFault()for EmptyResponse, MalformedResponse, Timeout - Delay simulation:
StubDelay()for testing timeout handling - Request verification:
VerifyCallMade(),VerifyNoCallsMade(),GetReceivedRequests() - Server management:
Reset(),ResetRequestHistory(),CreateClient()
- HTTP method stubs:
WireMockContainerFixture- Docker-based WireMock via Testcontainers:- Automatic container lifecycle management
- Admin API access via
CreateAdminClient() - Full isolation for CI/CD environments
- (NEW Issue #164)
EncinaRefitMockFixture<TApiClient>- Refit API client testing fixture:- Generic fixture for any Refit API interface
- Auto-configured Refit client via
CreateClient() - HTTP method stubs:
StubGet(),StubPost(),StubPut(),StubPatch(),StubDelete() - Error simulation:
StubError()with status code and error response - Delay simulation:
StubDelay()for timeout testing - Request verification:
VerifyCallMade(),VerifyNoCallsMade() - Server management:
Reset(),ResetRequestHistory()
- (NEW Issue #164)
WebhookTestingExtensions- Webhook endpoint testing:SetupWebhookEndpoint()- Generic webhook endpoint setupSetupOutboxWebhook()- Outbox pattern webhook endpoint (expects JSON POST)SetupWebhookFailure()- Simulate webhook failures for retry testingSetupWebhookTimeout()- Simulate webhook timeouts for resilience testingVerifyWebhookReceived()- Verify webhook was called with countVerifyNoWebhooksReceived()- Verify no webhooks were sentGetReceivedWebhooks()- Get all received webhook requestsGetReceivedWebhookBodies<T>()- Deserialize received webhook bodies
FaultTypeenum - Defines fault types: EmptyResponse, MalformedResponse, TimeoutReceivedRequestrecord - Captures request path, method, headers, body, timestamp- Fluent method chaining for stub configuration
- Automatic JSON serialization with camelCase naming
-
Encina.Testing.Shouldly Package - Open-source assertion extensions (Issue #429):
EitherShouldlyExtensions- Shouldly-style assertions forEither<TLeft, TRight>types:- Success assertions:
ShouldBeSuccess(),ShouldBeRight()with value/validator overloads - Error assertions:
ShouldBeError(),ShouldBeLeft()with validator overloads - EncinaError-specific:
ShouldBeValidationError(),ShouldBeNotFoundError(),ShouldBeAuthorizationError(),ShouldBeConflictError(),ShouldBeInternalError() - Code/message assertions:
ShouldBeErrorWithCode(),ShouldBeErrorContaining() - Async versions:
ShouldBeSuccessAsync(),ShouldBeErrorAsync(), etc.
- Success assertions:
EitherCollectionShouldlyExtensions- Batch operation assertions:ShouldAllBeSuccess(),ShouldAllBeError()for verifying all resultsShouldContainSuccess(),ShouldContainError()for at-least-one verificationShouldHaveSuccessCount(),ShouldHaveErrorCount()for exact counts- Helper methods:
GetSuccesses(),GetErrors()
- (NEW Issue #170)
StreamingShouldlyExtensions- IAsyncEnumerable assertions:ShouldAllBeSuccessAsync(),ShouldAllBeErrorAsync()for streaming resultsShouldContainSuccessAsync(),ShouldContainErrorAsync()for at-least-one verificationShouldHaveCountAsync(),ShouldHaveSuccessCountAsync(),ShouldHaveErrorCountAsync()for countsFirstShouldBeSuccessAsync(),FirstShouldBeErrorAsync()for first item assertionsShouldBeEmptyAsync(),ShouldNotBeEmptyAsync()for stream emptiness- EncinaError-specific:
ShouldContainValidationErrorForAsync(),ShouldNotContainAuthorizationErrorsAsync(),ShouldContainAuthorizationErrorAsync(),ShouldAllHaveErrorCodeAsync() - Helper:
CollectAsync()to materialize async streams
AggregateShouldlyExtensions- Event sourcing assertions:ShouldHaveRaisedEvent<T>()with predicate overloadsShouldHaveRaisedEvents<T>(count)for multiple eventsShouldNotHaveRaisedEvent<T>()for negative assertionsShouldHaveNoUncommittedEvents(),ShouldHaveUncommittedEventCount()ShouldHaveVersion(),ShouldHaveId()for aggregate state- Helpers:
GetRaisedEvents<T>(),GetLastRaisedEvent<T>()
- Open-source alternative to FluentAssertions ($130/dev/year)
-
FakeTimeProvider - Controllable time for testing (Issue #433):
FakeTimeProvider- Thread-safe TimeProvider implementation for testing time-dependent code- Time manipulation:
SetUtcNow(),Advance(),AdvanceToNextDay(),AdvanceToNextHour(),AdvanceMinutes(),AdvanceSeconds(),AdvanceMilliseconds() - Timer support via
CreateTimer()with fullITimerimplementation - Frozen time scope via
Freeze()method that restores time on dispose Reset()methods to restore time and clear timersActiveTimerCountproperty for timer verification- Support for one-shot and periodic timers
- Deterministic timer firing controlled by time advancement
- Concurrency Guarantees:
- Thread-safe:
SetUtcNow(),Advance()(atomic updates);CreateTimer()(concurrent creation);ActiveTimerCount,GetUtcNow()(read-only accessors) - Not thread-safe: Manual timer manipulation (
Change(),Dispose()on individual timers); composed sequences (e.g., read-then-advance across threads). These require external synchronization.
- Thread-safe:
-
Encina.Testing.Fakes Package - Test doubles for Encina components (Issue #426):
FakeEncina- In-memory IEncina implementation with verification methodsFakeOutboxStore,FakeInboxStore,FakeSagaStore- Messaging store fakesFakeScheduledMessageStore,FakeDeadLetterStore- Additional store fakes- Thread-safe implementations preserving insertion order
- Fluent API for setup:
SetupResponse(),SetupError(),SetupStream() - Verification methods:
WasSent(),WasPublished(),GetSentRequests() - DI extensions:
AddFakeEncina(),AddFakeStores(),AddEncinaTestingFakes()
-
Encina.DomainModeling Package - DDD tactical pattern building blocks (Issues #367, #369, #374):
Entity<TId>- Base class for entities with identity-based equalityValueObject- Base class for value objects with structural equalitySingleValueObject<TValue>- Wrapper for single-value primitives with implicit conversionStronglyTypedId<TValue>- Base class for type-safe identifiers with comparison and equalityGuidStronglyTypedId<TSelf>- GUID-based strongly typed IDs withNew(),From(),TryParse(),EmptyIntStronglyTypedId<TSelf>,LongStronglyTypedId<TSelf>,StringStronglyTypedId<TSelf>- Numeric and string IDsAggregateRoot<TId>- Base class for aggregate roots with domain event supportAuditableAggregateRoot<TId>- Aggregate withCreatedAtUtc,CreatedBy,ModifiedAtUtc,ModifiedBySoftDeletableAggregateRoot<TId>- Aggregate with soft delete (IsDeleted,DeletedAtUtc,DeletedBy)DomainEventandRichDomainEvent- Base records for domain events with correlation/causation trackingIntegrationEvent- Base record for cross-boundary events with versioningIDomainEventToIntegrationEventMapper<TDomain, TIntegration>- Anti-corruption layer mapper interface- Auditing interfaces:
IAuditable,ISoftDeletable,IConcurrencyAware,IVersioned
-
Specification Pattern (Issue #295) - Query composition and encapsulation:
Specification<T>- Base class withAnd(),Or(),Not()compositionQuerySpecification<T>- Extended specification with includes, ordering, paging, tracking optionsQuerySpecification<T, TResult>- Specification with projection support viaSelector- Expression tree composition for LINQ provider compatibility
- Implicit conversion to
Expression<Func<T, bool>>
-
Business Rules Pattern (Issue #372) - Domain invariant validation:
IBusinessRuleinterface withErrorCode,ErrorMessage,IsSatisfied()BusinessRuleabstract base classBusinessRuleViolationExceptionfor throw-based validationBusinessRuleErrorandAggregateBusinessRuleErrorrecords for ROPBusinessRuleExtensions:Check(),CheckFirst(),CheckAll(),ThrowIfNotSatisfied(),ThrowIfAnyNotSatisfied()
-
Domain Service Marker (Issue #377) - Semantic clarity:
IDomainServicemarker interface for domain services identification
-
Anti-Corruption Layer Pattern (Issue #299) - Bounded context translation:
TranslationErrorrecord with factory methods (UnsupportedType,MissingRequiredField,InvalidFormat)IAntiCorruptionLayer<TExternal, TInternal>sync interfaceIAsyncAntiCorruptionLayer<TExternal, TInternal>async variantAntiCorruptionLayerBase<TExternal, TInternal>with helper methods
-
Result Pattern Extensions (Issue #468) - Fluent API for Either type:
- Combination:
Combine()for 2/3/4 values and collections - Conditional:
When(),Ensure(),OrElse(),GetOrDefault(),GetOrElse() - Side effects:
Tap(),TapError() - Async:
BindAsync(),MapAsync(),TapAsync()(forTask<Either>andEither)- New Encina extensions in
Encina.Core.Extensions.EitherAsyncExtensions - Namespace:
using Encina.Core.Extensions; - Example:
Task<Either<L, R>> BindAsync<L, R, R2>(this Task<Either<L, R>> task, Func<R, Task<Either<L, R2>>> f)
- New Encina extensions in
- Conversion:
ToOption(),ToEither()(from Option),GetOrThrow()
- Combination:
-
Rich Domain Event Envelope (Issue #368) - Extended domain event metadata:
IDomainEventMetadatainterface withCorrelationId,CausationId,UserId,TenantId,AdditionalMetadataDomainEventMetadatarecord with factory methods (Empty,WithCorrelation,WithCausation)DomainEventEnvelope<TEvent>- Wraps events with metadata, envelope ID, and timestampDomainEventExtensions- Fluent API:ToEnvelope(),WithMetadata(),WithCorrelation(),Map()
-
Integration Event Extensions (Issue #373) - Cross-context event mapping:
IAsyncDomainEventToIntegrationEventMapper<TDomain, TIntegration>- Async mapper interfaceIFallibleDomainEventToIntegrationEventMapper<TDomain, TIntegration, TError>- ROP mapper with EitherIIntegrationEventPublisher- Publisher interface withPublishAsync(),PublishManyAsync()IFallibleIntegrationEventPublisher<TError>- ROP publisher variantIntegrationEventMappingErrorandIntegrationEventPublishError- Structured error typesIntegrationEventMappingExtensions-MapTo(),MapToAsync(),MapAll(),TryMapTo(),Compose()
-
Generic Repository Pattern (Issue #380) - Provider-agnostic data access:
IReadOnlyRepository<TEntity, TId>- Query operations with Specification supportIRepository<TEntity, TId>- Full CRUD operations extending read-onlyIAggregateRepository<TAggregate, TId>- Aggregate-specific withSaveAsync()PagedResult<T>- Pagination withTotalPages,HasPreviousPage,HasNextPage,Map()RepositoryError- Error types (NotFound,AlreadyExists,ConcurrencyConflict,OperationFailed)RepositoryExtensions-GetByIdOrErrorAsync(),GetByIdOrThrowAsync(),AddIfNotExistsAsync(),UpdateIfExistsAsync()EntityNotFoundException- Exception for entity lookup failures
-
Ports & Adapters Factory Pattern (Issue #475) - Hexagonal Architecture support:
IPort,IInboundPort,IOutboundPort- Port marker interfacesIAdapter<TPort>- Adapter marker interface with port constraintAdapterBase<TPort>- Base class withExecute(),ExecuteAsync()for error handlingAdapterError- Error types (OperationFailed,Cancelled,NotFound,CommunicationFailed,ExternalError)PortRegistrationExtensions- DI registration:AddPort<TPort, TAdapter>(),AddPortsFromAssembly()
-
Result/DTO Mapping with ROP Semantics (Issue #478) - Domain-to-DTO mapping:
IResultMapper<TDomain, TDto>- Sync mapper returningEither<MappingError, TDto>IAsyncResultMapper<TDomain, TDto>- Async mapper variantIBidirectionalMapper<TDomain, TDto>- Two-way mapping withMapToDomain()IAsyncBidirectionalMapper<TDomain, TDto>- Async bidirectional variantMappingError- Error types (NullProperty,ValidationFailed,ConversionFailed,EmptyCollection)ResultMapperExtensions-MapAll(),MapAllCollectErrors(),TryMap(),Compose()ResultMapperRegistrationExtensions-AddResultMapper(),AddResultMappersFromAssembly()
-
Application Services Interface (Issue #479) - Use case orchestration:
IApplicationService- Marker interface for application servicesIApplicationService<TInput, TOutput>- Typed service withExecuteAsync()IApplicationService<TOutput>- Parameterless service for scheduled tasksIVoidApplicationService<TInput>- Service returningUniton successApplicationServiceError- Error types (NotFound,ValidationFailed,BusinessRuleViolation,ConcurrencyConflict,InfrastructureFailure,Unauthorized)ApplicationServiceExtensions-ToApplicationServiceError()for error conversionApplicationServiceRegistrationExtensions-AddApplicationService(),AddApplicationServicesFromAssembly()
-
Bounded Context Patterns (Issues #379, #477) - Strategic DDD support:
BoundedContextAttribute- Mark types with bounded context membershipContextMap- Document relationships between contexts with fluent APIContextRelationshipenum - Conformist, ACL, SharedKernel, CustomerSupplier, PublishedLanguage, SeparateWays, Partnership, OpenHostContextRelationrecord - Stores upstream/downstream context with relationship typeBoundedContextModuleabstract class - Modular monolith module base with DI configurationIBoundedContextModuleinterface - Module contract withName,Dependencies,ConfigureServices()BoundedContextValidator- Validate circular dependencies and orphaned consumersBoundedContextError- Error types (OrphanedConsumer,CircularDependency,ValidationFailed)BoundedContextExtensions-GetBoundedContextName(),AddBoundedContextModules(),ValidateBoundedContexts()- Mermaid diagram generation via
ToMermaidDiagram()
-
Domain Language DSL (Issue #381) - Fluent domain building:
DomainBuilder<T, TBuilder>- CRTP fluent builder with ROPAggregateBuilder<TAggregate, TId, TBuilder>- Aggregate builder with business rule validationDomainBuilderError- Error types (MissingValue,ValidationFailed,BusinessRulesViolated,InvalidState)DomainDslExtensions- Fluent specification checks:Is(),Satisfies(),Violates(),Passes(),Fails()- Fluent validation:
EnsureValid(),EnsureNotNull(),EnsureNotEmpty()returning Either - Common Domain Types:
Quantitystruct - Non-negative quantity with arithmetic operatorsPercentagestruct - 0-100 percentage withApplyTo(),AsFraction,ComplementDateRangestruct - Date range withContains(),Overlaps(),Intersect(),ExtendBy()TimeRangestruct - Time range withDuration,Contains(),Overlaps()
-
Vertical Slice + Hexagonal Hybrid Architecture (Issue #476) - Feature slices:
FeatureSliceabstract class - Base for vertical slices withFeatureName,ConfigureServices()IFeatureSliceWithEndpoints- Slices with HTTP endpoint configurationIFeatureSliceWithDependencies- Slices with explicit inter-slice dependenciesSliceDependencyrecord - Represents dependency on another slice (optional flag)FeatureSliceConfiguration- Fluent configuration:AddSlice<T>(),AddSlicesFromAssembly()FeatureSliceExtensions-AddFeatureSlices(),AddFeatureSlice<T>(),GetFeatureSlices(),GetFeatureSlice()FeatureSliceError- Error types (MissingDependency,CircularDependency,RegistrationFailed)- Use Case Handlers:
IUseCaseHandlermarker interfaceIUseCaseHandler<TInput, TOutput>- Handler with input and outputIUseCaseHandler<TInput>- Command handler (void output)UseCaseHandlerExtensions-AddUseCaseHandler<T>(),AddUseCaseHandlersFromAssembly()
-
Comprehensive test coverage: 175 unit tests, 275 property tests, 531 contract tests, 80 guard tests (1061 total).
- Note: Load tests (
[Trait("Category", "Load")]) are excluded from default CI runs due to a .NET 10 JIT bug. - Known Issue - CLR Crash on .NET 10 (Encina Issue #5):
- Scope: Affects load tests only (NBomber +
IAsyncEnumerable<Either<EncinaError, T>>under high concurrency). Production code is not affected. - Affected Versions: .NET 10.0.x (all current releases)
- Upstream Bug: dotnet/runtime#121736 - Fixed in .NET 11, awaiting .NET 10.x backport
- CI/CD Mitigation: Load tests are excluded via project name pattern (
*LoadTests*) in.github/workflows/ci.yml. Dedicated load test workflow runs separately with workaround. - Local Workaround: Set
DOTNET_JitObjectStackAllocationConditionalEscape=0before running load tests - Internal Docs: See
docs/releases/pre-v0.10.0/README.md"Known Issues" section
- Scope: Affects load tests only (NBomber +
- Note: Load tests (
AI/LLM Patterns Issues (12 new features planned based on December 29, 2025 research)
- MCP (Model Context Protocol) Support (Issue #481) - MCP server/client integration
MCPServerBuilderfor creating MCP servers in C#MCPClientBehaviorfor consuming external MCP tools- Native integration with
IEncina- expose handlers as AI tools - SSE and HTTP transports
- Azure Functions support for remote MCP servers
- Priority: HIGH - Industry standard adopted by OpenAI, Anthropic, Microsoft
- Semantic Caching Pipeline Behavior (Issue #482) - Embedding-based cache
SemanticCachingPipelineBehavior<TRequest, TResponse>ISemanticCacheProviderabstraction with Redis, Qdrant providers- Similarity threshold configurable (default 0.95)
- Reduces LLM costs by 40-70%, latency from 850ms to <120ms
- New packages planned:
Encina.AI.Caching.Redis,Encina.AI.Caching.Qdrant - Priority: HIGH - Major cost reduction
- AI Guardrails & Safety Pipeline (Issue #483) - Security for AI applications
PromptInjectionDetectionBehavior- OWASP #1 threat for LLMsPIIDetectionBehavior- Detect and redact sensitive dataContentModerationBehavior- Filter harmful contentIGuardrailProviderabstraction with Azure Prompt Shields, AWS Bedrock, OpenGuardrails- Configurable actions: Block, Warn, Log, Redact
- New package planned:
Encina.AI.Safety - Priority: HIGH - Essential for production AI
- RAG Pipeline Patterns (Issue #484) - Retrieval-Augmented Generation
IRagPipeline<TQuery, TResponse>abstraction- Query rewriting (multi-query, HyDE), chunk retrieval, re-ranking
- Hybrid search (keyword + semantic)
- Agentic RAG with query planning
- Citation/source tracking
- New package planned:
Encina.AI.RAG - Priority: HIGH - Most demanded LLM pattern
- Token Budget & Cost Management (Issue #485) - LLM cost control
TokenBudgetPipelineBehavior<TRequest, TResponse>ITokenBudgetStorewith Redis/SQL providers- Per-user/tenant/request type limits
- Cost estimation and reporting
- Automatic fallback to cheaper models
- Priority: MEDIUM - Enterprise cost control
- LLM Observability Integration (Issue #486) - AI-specific metrics
- Enhancement to
Encina.OpenTelemetry LLMActivityEnricherwith GenAI semantic conventions- Token usage metrics (input/output/cached/reasoning)
- Time to first token (TTFT) measurement
- Cost attribution per model/user/tenant
- Integration with Langfuse, Datadog LLM Observability
- Priority: HIGH - Production monitoring
- Enhancement to
- Multi-Agent Orchestration Patterns (Issue #487) - AI agent workflows
IAgentandIAgentHandler<TRequest, TResponse>interfaces- Orchestration patterns: Sequential, Concurrent, Handoff, GroupChat, Magentic
IAgentSelectorfor dynamic routing- Human-in-the-Loop (HITL) support
- Cross-language agents via MCP
- Semantic Kernel adapter:
SemanticKernelAgentAdapter - New package planned:
Encina.Agents - Priority: MEDIUM - Microsoft Agent Framework
- Structured Output Handler (Issue #488) - JSON schema enforcement
IStructuredOutputHandler<TRequest, TOutput>interfaceIJsonSchemaGeneratorwith System.Text.Json support- Response validation with retry on failure
- Fallback parsing for edge cases
- Priority: MEDIUM - Schema guarantees
- Function Calling Orchestration (Issue #489) - LLM tool use
IFunctionCallingOrchestratorinterface[AIFunction]attribute for handler decoration- Auto/Manual/Confirm invocation modes
- Parallel function calls support
- Semantic Kernel plugin adapter:
EncinaPluginAdapter - Priority: MEDIUM - Native LLM feature
- Vector Store Abstraction (Issue #490) - Embedding storage
IVectorStoreandIVectorRecordabstractions- Integration with
IEmbeddingGenerator(Microsoft.Extensions.AI) - Metadata filtering, hybrid search, batch operations
- New packages planned:
Encina.VectorData,Encina.VectorData.Qdrant,Encina.VectorData.AzureSearch,Encina.VectorData.Milvus,Encina.VectorData.Chroma,Encina.VectorData.InMemory - Priority: HIGH - Foundation for RAG and Semantic Cache
- Prompt Management & Versioning (Issue #491) - Enterprise prompt governance
IPromptRepositoryandIPromptTemplateEngine- Versioned prompt templates with A/B testing
- Prompt analytics and performance tracking
- Storage providers: FileSystem (YAML/JSON), Database, Git
- Priority: LOW - Enterprise governance
- AI Streaming Pipeline Enhancement (Issue #492) - Token-level streaming
IAIStreamRequest<TChunk>andTokenChunktypesBackpressureStreamBehaviorfor slow consumers- SSE endpoint helper in
Encina.AspNetCore - Time to first token (TTFT) measurement
- Integration with
IChatClient.CompleteStreamingAsync - Priority: MEDIUM - UX enhancement
Hexagonal Architecture Patterns Issues (10 new features planned based on December 29, 2025 research)
-
Domain Events vs Integration Events (Issue #470) - Formal separation between domain events and integration events
DomainEventbase class with AggregateId, OccurredAtUtc, VersionIntegrationEventbase class extending INotification with EventType, CorrelationIdIDomainEventHandler<TEvent>for in-process synchronous processing- Integration with existing Outbox pattern for integration event publishing
- Priority: CRITICAL - Foundational for DDD/microservices
- Specification Pattern (Issue #471) - Composable, testable query encapsulation
Specification<T>andSpecification<T, TResult>base classesISpecificationRepository<T>with EF Core and Dapper support- And/Or/Not composition operators
- New packages planned:
Encina.Specifications,Encina.Specifications.EFCore - Priority: CRITICAL - High demand (~9M downloads for Ardalis.Specification)
- Value Objects & Aggregates (Issue #472) - DDD building blocks
ValueObjectwith structural equalityStronglyTypedId<T>for type-safe identifiersEntity<TId>for non-root entitiesAggregateRoot<TId>with domain events and version for concurrency- New package planned:
Encina.DDD - Priority: CRITICAL - Core DDD patterns
- Domain Services (Issue #473) - IDomainService marker interface
- Pure domain logic without infrastructure dependencies
- Auto-registration via
AddDomainServicesFromAssembly() - Priority: HIGH - Complements handlers with domain logic
- Anti-Corruption Layer (Issue #474) - External system isolation
IAntiCorruptionLayer<TExternal, TDomain>bidirectional interfaceIInboundAntiCorruptionLayerandIOutboundAntiCorruptionLayer- ROP semantics for all translations
- New package planned:
Encina.Hexagonal - Priority: HIGH - Essential for integrations
- Ports & Adapters Factory (Issue #475) - Hexagonal architecture formalization
IPort,IInboundPort,IOutboundPortmarker interfacesAddPort<TPort, TAdapter>()registration methodAdapterBase<TPort>with logging and error handling- Priority: HIGH - Formalizes hexagonal boundaries
- Vertical Slice + Hexagonal Hybrid (Issue #476) - Feature organization
IFeatureSliceextendingIModuleMapEncinaSlices()for endpoint mapping- Combines vertical slice organization with hexagonal boundaries
- Priority: MEDIUM - Architectural guidance
- Bounded Context Modules (Issue #477) - Module boundary contracts
IBoundedContextModulewith PublishedIntegrationEvents and ConsumedIntegrationEventsIContextMapfor relationship visualization- Mermaid diagram generation
- Priority: MEDIUM - SaaS and modular monolith support
- Result/DTO Mapping (Issue #478) - Domain to DTO with ROP
IResultMapper<TDomain, TDto>interfaceIAsyncResultMapper<TDomain, TDto>for async mappingsMapAll()andMapAllCollectErrors()extensions- Priority: MEDIUM
- Application Services (Issue #479) - Use case orchestration
IApplicationService<TInput, TOutput>interface- Clear separation from Domain Services (logic vs orchestration)
- Priority: MEDIUM
-
New labels created for Hexagonal Architecture Patterns:
area-application-services- Application Services and use case orchestration (#2E8B57)area-ports-adapters- Ports and Adapters (Hexagonal Architecture) patterns (#4169E1)area-hexagonal- Hexagonal Architecture patterns and infrastructure (#6A5ACD)area-dto-mapping- DTO mapping and object transformation patterns (#9370DB)clean-architecture- Clean Architecture patterns and structure (#32CD32)abp-inspired- Pattern inspired by ABP Framework (#FF6B6B)ardalis-inspired- Pattern inspired by Steve Smith (Ardalis) libraries (#FF8C00)
TDD Patterns Issues (12 new features planned based on December 29, 2025 research)
-
Encina.Testing.Fakes (Issue #426) - Test doubles for IEncina and messaging stores
FakeEncina : IEncinawith configurable handlersFakeOutboxStore,FakeInboxStore,FakeSagaStore,FakeScheduledMessageStore- Verification methods:
VerifySent<T>(),VerifyPublished<T>() - Implemented:
Encina.Testing.Fakes - Priority: HIGH - Foundational for unit testing
- Encina.Testing.Respawn (Issue #427) - Intelligent database reset with Respawn
RespawnDatabaseFixture<TContainer>base class- FK-aware deterministic deletion (3x faster than truncate)
- Integration with existing Testcontainers fixtures
- Implemented:
Encina.Testing.Respawn - Priority: HIGH - Essential for integration testing
- Encina.Testing.WireMock (Issue #428) - HTTP API mocking for integration tests
EncinaWireMockFixturewith fluent stubbing API- Fault simulation for resilience testing
- Implemented:
Encina.Testing.WireMock - Priority: HIGH - External API testing
- Encina.Testing.Shouldly (Issue #429) - Open-source assertions (FluentAssertions alternative)
ShouldBeSuccess(),ShouldBeError()forEither<EncinaError, T>- Replaces FluentAssertions after commercial license change (Jan 2025)
- Implemented:
Encina.Testing.Shouldly - Priority: HIGH - Open-source assertion library
- Encina.Testing.Verify (Issue #430) - Snapshot testing integration
VerifyEither(),VerifyUncommittedEvents(),VerifySagaState()- Automatic scrubbers for timestamps and GUIDs
- New package planned:
Encina.Testing.Verify - Priority: MEDIUM
- Encina.Testing.Bogus (Issue #431) - Realistic test data generation
EncinaFaker<TRequest>base class with conventions- Pre-built fakers for messaging entities
- New package planned:
Encina.Testing.Bogus - Priority: MEDIUM
- Encina.Testing.Architecture (Issue #432) - Architectural rules enforcement
EncinaArchitectureRuleswith CQRS/DDD rules- ArchUnitNET integration
- New package planned:
Encina.Testing.Architecture - Priority: MEDIUM
- FakeTimeProvider (Issue #433) - Time control for testing
FakeTimeProvider : TimeProvider(.NET 8+ compatible)Advance(),SetUtcNow(),Freeze()methods- Priority: MEDIUM - Added to Encina.Testing core
- BDD Specification Testing (Issue #434) - Given/When/Then for handlers
HandlerSpecification<TRequest, TResponse>base class- Extension of existing
AggregateTestBasepattern - Priority: LOW
- Encina.Testing.FsCheck (Issue #435) - Property-based testing extensions
EncinaArbitrariesfor Encina typesEncinaPropertiesfor common invariants- New package planned:
Encina.Testing.FsCheck - Priority: LOW - Advanced testing
- Encina.Testing.Pact (Issue #436) - Consumer-Driven Contract Testing
EncinaPactConsumerBuilder,EncinaPactProviderVerifier- Microservices contract verification
- New package planned:
Encina.Testing.Pact - Priority: LOW - Microservices focus
- Stryker.NET Configuration (Issue #437) - Mutation testing templates
stryker-config.jsontemplates- GitHub Actions and Azure DevOps workflows
encina generate strykerCLI command- Priority: LOW - Quality tooling
-
New labels created for TDD Patterns:
testing-property-based- Property-based testing and invariant verification (#9B59B6)testing-contract- Contract testing and consumer-driven contracts (#8E44AD)testing-bdd- Behavior-driven development and Given/When/Then patterns (#A569BD)testing-time-control- Time manipulation and FakeTimeProvider for testing (#7D3C98)testing-assertions- Assertion libraries and fluent assertions (#6C3483)testing-database-reset- Database cleanup and reset between tests (#5B2C6F)
Developer Tooling & DX Issues (11 new features planned based on December 29, 2025 research)
-
Encina.Analyzers (Issue #438) - Roslyn analyzers and code fixes
- 10+ analyzers: ENC001 (CancellationToken), ENC002 (Validator missing), ENC003 (Saga compensation)
- Code fixes: generate handler skeleton, add CancellationToken, implement IIdempotentRequest
- Compatible with NativeAOT and Source Generators
- New package planned:
Encina.Analyzers - Priority: HIGH - Compile-time error detection
- Saga Visualizer (Issue #439) - State machine diagram generation
- Generate Mermaid, Graphviz (DOT), PlantUML from saga definitions
- Runtime visualization with current state highlighted
- CLI:
encina visualize saga OrderFulfillmentSaga --output mermaid - Priority: MEDIUM - Documentation and debugging
- Encina.Aspire (Issue #440) - .NET Aspire integration package
EncinaResourceas first-class Aspire resource- Dashboard panel for Outbox, Inbox, Sagas
- Health checks and OTLP pre-configured
- New packages planned:
Encina.Aspire,Encina.Aspire.Hosting - Priority: HIGH - Modern .NET stack integration
- Encina.Diagnostics (Issue #441) - Enhanced exception formatting
- Pretty-print for
EncinaErrorwith box-drawing characters - Demystified stack traces (Ben.Demystifier-inspired)
- Validation errors grouped by property
- ANSI colors with plain text fallback
- New package planned:
Encina.Diagnostics - Priority: MEDIUM - Developer experience
- Pretty-print for
- Hot Reload Support (Issue #442) - Handler hot reload
- Integration with
MetadataUpdateHandler.ClearCache - Automatic pipeline cache invalidation
- Development-only (no production impact)
- Priority: MEDIUM - Inner loop improvement
- Integration with
- AI-Ready Request Tracing (Issue #443) - Request/response capture
- Automatic serialization with PII redaction
[Trace]attribute with RedactProperties- AI-compatible export format
- Sampling strategies (errors always, slow requests, random)
- Priority: MEDIUM - Modern debugging
- Enhanced Testing Fixtures (Issue #444) - Testing improvements
EncinaTestFixturewith fluent builder- Either assertions:
ShouldBeSuccess(),ShouldBeError() - Time-travel for sagas:
AdvanceTimeBy() - Outbox/Inbox assertions:
OutboxShouldContain<T>() - Priority: MEDIUM - Testing DX
- Encina.Dashboard (Issue #445) - Developer dashboard web UI
- Local web UI for debugging (Hangfire Dashboard-style)
- Panels: Handlers, Pipeline, Outbox, Inbox, Sagas, Cache, Errors
- Real-time updates via SignalR
- Actions: Retry Outbox, Cancel Saga, Invalidate Cache
- New package planned:
Encina.Dashboard - Priority: HIGH - Development visibility
- Encina.OpenApi (Issue #446) - OpenAPI integration
- Auto-generate OpenAPI spec from Commands/Queries
app.MapEncinaEndpoints()for endpoint generation- FluentValidation constraints in schema
- OpenAPI 3.1 support (.NET 10)
- New package planned:
Encina.OpenApi - Priority: MEDIUM - API-first development
- Dev Containers Support (Issue #447) - Container development
.devcontainer/configuration- GitHub Codespaces support
- Docker Compose with Postgres, Redis, RabbitMQ
- CLI:
encina add devcontainer --services postgres,redis - Priority: LOW - Developer onboarding
- Interactive Documentation (Issue #448) - Documentation site
- Docusaurus or DocFX site
- Playground with executable code
- API reference from XML docs
- Versioned documentation
- Priority: LOW - Community growth
-
New labels created for Developer Tooling:
area-analyzers- Roslyn analyzers and code fixes (#5C2D91)area-visualization- Visualization and diagram generation (#9B59B6)area-dashboard- Developer dashboard and monitoring UI (#E74C3C)area-diagnostics- Diagnostics, error formatting, and debugging aids (#E67E22)area-devcontainers- Dev Containers and Codespaces support (#0DB7ED)area-documentation-site- Documentation website and interactive docs (#3498DB)
.NET Aspire Integration Patterns Issues (10 new features planned based on December 29, 2025 research)
-
Encina.Aspire.Hosting (Issue #416) - AppHost integration package
WithEncina()extension method forIResourceBuilder<ProjectResource>- Custom
EncinaResourcefor Dashboard visibility - Configuration propagation via environment variables
- Custom commands: Process Outbox, Retry Dead Letters, Cancel Saga
- New package planned:
Encina.Aspire.Hosting - Priority: MEDIUM - Foundational for Aspire integration
- Encina.Aspire.ServiceDefaults (Issue #417) - Service Defaults extension
AddEncinaDefaults()forIHostApplicationBuilder- OpenTelemetry integration (tracing + metrics)
- Health checks for all messaging patterns
- Standard Resilience pipeline integration
- New package planned:
Encina.Aspire.ServiceDefaults - Priority: HIGH - Centralizes cross-cutting concerns
- Encina.Aspire.Testing (Issue #418) - Testing integration
WithEncinaTestSupport()forDistributedApplicationTestingBuilder- Assertion extensions:
AssertOutboxContains<T>(),AssertSagaCompleted<T>() - Test data reset helpers (clear outbox, inbox, sagas)
- Wait helpers:
WaitForOutboxProcessing(),WaitForSagaCompletion() - New package planned:
Encina.Aspire.Testing - Priority: HIGH - "Largest gap" per official Aspire roadmap
- Encina.Aspire.Dashboard (Issue #419) - Dashboard extensions
- Custom commands via
WithCommand()API - Encina-specific metrics visibility
- Commands:
process-outbox,retry-dead-letters,cancel-saga - New package planned:
Encina.Aspire.Dashboard - Priority: MEDIUM - Improves observability
- Custom commands via
- Encina.Dapr (Issue #420) - Dapr building blocks integration
- Dapr State Store for Saga/Scheduling state
- Dapr Pub/Sub for Outbox publishing
- Dapr Service Invocation for inter-service commands
- Dapr Actors for saga orchestration (optional)
- New package planned:
Encina.Dapr - Priority: MEDIUM - CNCF graduated, high demand
- Encina.Aspire.Deployment (Issue #421) - Deployment publishers
- Azure Container Apps publisher with Encina infrastructure
- Kubernetes manifests generation
- Docker Compose environment support
- KEDA scaling rules for processors
- New package planned:
Encina.Aspire.Deployment - Priority: LOW - azd already automates much
- Encina.Aspire.AI (Issue #422) - AI Agent & MCP Server support
- MCP Server to expose Encina state to AI agents
- Tools:
analyze_saga_failure,retry_dead_letter - Azure AI Foundry integration
- Dashboard Copilot integration
- New package planned:
Encina.Aspire.AI - Priority: LOW - Roadmap 2026
- Modular Monolith Architecture Support (Issue #423)
IEncinaModuleinterface with lifecycle hooksWithEncinaModules()for AppHost- Inter-module communication via Encina messaging
- Module isolation with separate DbContexts
- Priority: MEDIUM - Trending architecture 2025
- Multi-Repo Support (Issue #424)
AddEncinaExternalService()for services in other repos- Service discovery: Kubernetes, Consul, DNS
- Shared message broker configuration
- Contract-first approach
- Priority: MEDIUM - Enterprise demand
- Hot Reload Support (Issue #425)
- Hot reload of handlers during development
- Integration with
MetadataUpdateHandler - State preservation (outbox, inbox, sagas)
- Dashboard indication during reload
- Priority: MEDIUM - Developer experience
-
New labels created for Aspire integration:
area-aspire- Aspire hosting, orchestration, and deployment (#512BD4)area-mcp- Model Context Protocol and AI agent integration (#8B5CF6)area-hot-reload- Hot reload and live code updates (#F59E0B)
Cloud-Native Patterns Issues (11 new features planned based on December 29, 2025 research)
- Encina.Aspire (Issue #449) - .NET Aspire integration
AddEncinaAspireDefaults()extension method- Service Discovery integration for distributed handlers
- OpenTelemetry pre-configured for Encina pipeline
- Health checks for Outbox, Inbox, Sagas
- Aspire Dashboard integration
- New package planned:
Encina.Aspire - Priority: HIGH - Official Microsoft cloud-native stack
- Encina.Dapr (Issue #450) - Dapr Building Blocks integration
DaprSagaStore,DaprOutboxStore,DaprInboxStorevia Dapr State APIDaprOutboxPublishervia Dapr Pub/SubDaprDistributedLockProvidervia Dapr Lock API- Secrets injection via
[DaprSecret]attribute - Cloud-agnostic: same code on AWS, Azure, GCP, on-prem
- New package planned:
Encina.Dapr - Priority: HIGH - CNCF graduated, multi-cloud demand
- Encina.FeatureFlags (Issue #451) - Feature flags abstraction
IFeatureFlagProviderabstraction[Feature("key")]attribute for handler injectionFeatureFlagInjectionBehaviorpipeline behavior- Providers: ConfigCat, LaunchDarkly, Azure App Configuration, OpenFeature
- New packages planned:
Encina.FeatureFlags,Encina.FeatureFlags.ConfigCat,Encina.FeatureFlags.LaunchDarkly,Encina.FeatureFlags.OpenFeature - Priority: MEDIUM - Progressive deployment enabler
- Encina.Secrets (Issue #452) - Secrets management abstraction
ISecretsProviderabstraction[Secret("key")]attribute for DI injection- Secret rotation monitoring (optional)
- Providers: Azure Key Vault, AWS Secrets Manager, HashiCorp Vault
- New packages planned:
Encina.Secrets,Encina.Secrets.AzureKeyVault,Encina.Secrets.AwsSecretsManager,Encina.Secrets.HashiCorpVault - Priority: MEDIUM - Security best practice
- Encina.ServiceDiscovery (Issue #453) - Service discovery abstraction
IServiceDiscoveryProviderabstraction- Load balancing strategies: RoundRobin, Random, LeastConnections
IEncina.SendToService<>()extension methods- Providers: Kubernetes DNS, Consul, Aspire
- New packages planned:
Encina.ServiceDiscovery,Encina.ServiceDiscovery.Kubernetes,Encina.ServiceDiscovery.Consul - Priority: MEDIUM - Microservices fundamental
- Encina.HealthChecks (Issue #454) - Kubernetes health probes
OutboxHealthCheck,InboxHealthCheck,SagaHealthCheck,HandlerHealthCheck- Separate endpoints:
/health/live,/health/ready,/health/startup - Integration with
Microsoft.Extensions.Diagnostics.HealthChecks - New package planned:
Encina.HealthChecks - Priority: MEDIUM - Kubernetes deployment essential
- Encina.GracefulShutdown (Issue #455) - Kubernetes graceful termination
IInFlightRequestTrackerfor active request trackingInFlightTrackingBehaviorpipeline behavior- Pre-stop delay for LB drain
- Outbox flush before shutdown
- New package planned:
Encina.GracefulShutdown - Priority: MEDIUM - K8s reliability essential
- Encina.MultiTenancy (Issue #456) - Multi-tenancy for SaaS
- Tenant resolution: Header, Subdomain, Route, Claim, Custom
- Data isolation: Row, Schema, Database strategies
TenantAwareOutboxStore,TenantAwareSagaStore,TenantAwareInboxStore- GDPR data residency support
- New package planned:
Encina.MultiTenancy - Priority: MEDIUM - SaaS market enabler
- Encina.CDC (Issue #457) - Change Data Capture for Outbox
ICdcProviderabstraction for change streaming- CDC Orchestrator hosted service
- Providers: SQL Server CDC, PostgreSQL Logical Replication, Debezium
- Near real-time message capture, minimal database load
- New packages planned:
Encina.CDC,Encina.CDC.SqlServer,Encina.CDC.PostgreSQL - Priority: LOW - Alternative to polling, high complexity
- Encina.ApiVersioning (Issue #458) - Handler versioning support
[ApiVersion("1.0")]attribute for handlers- Version resolution: Header, Query, Path, MediaType
- Deprecation support with Sunset header
- Version discovery endpoint
- New package planned:
Encina.ApiVersioning - Priority: LOW - API evolution support
- Encina.Orleans (Issue #459) - Orleans virtual actors integration
IGrainHandler<,>interface- Orleans-based request dispatcher
- Saga grains with Orleans state and reminders
- Scheduling via grain timers
- New package planned:
Encina.Orleans - Priority: LOW - High-concurrency niche
Microservices Architecture Patterns Issues (12 new features planned based on December 29, 2025 research)
-
Service Discovery & Configuration Management (Issue #382) - Foundational microservices pattern
IServiceDiscoverywithResolveAsync,RegisterAsync,DeregisterAsync,WatchAsyncIConfigurationProviderfor externalized configuration- Multiple backends: Consul, Kubernetes DNS, .NET Aspire
- New packages planned:
Encina.ServiceDiscovery,Encina.ServiceDiscovery.Consul,Encina.ServiceDiscovery.Kubernetes,Encina.ServiceDiscovery.Aspire - Priority: CRITICAL - Fundamental pattern missing from Encina
- API Gateway / Backends for Frontends (BFF) (Issue #383) - Essential modern architecture pattern
IBffRequestAdapterfor proxying with Encina pipelineIResponseAggregator<T>for combining multiple service responses[BffRoute],[AggregateFrom]declarative attributes- Microsoft YARP integration
- New packages planned:
Encina.BFF,Encina.BFF.YARP,Encina.BFF.Aggregation - Priority: CRITICAL - Very high demand in 2025
- Domain Events vs Integration Events Separation (Issue #384) - DDD best practice
IDomainEventfor in-process bounded context eventsIIntegrationEventwithEventId,SourceService,VersionIIntegrationEventMapper<TDomain, TIntegration>for automatic translationDomainToIntegrationEventBehaviorfor Outbox auto-publishing- Priority: CRITICAL - Inspired by MassTransit, NServiceBus
- Multi-Tenancy Support (Issue #385) - SaaS-critical pattern
ITenantContextwithCurrentTenant,IsolationLevelTenantIsolationLevel: SharedSchema, SeparateSchema, SeparateDatabaseITenantResolverwith Header, Claims, Subdomain, Route resolversTenantFilteringPipelineBehaviorfor automatic query filtering- EF Core integration with automatic tenant filtering
- New packages planned:
Encina.MultiTenancy,Encina.MultiTenancy.EntityFrameworkCore - Priority: HIGH - Essential for SaaS applications
- Anti-Corruption Layer (ACL) (Issue #386) - Legacy integration pattern
IAntiCorruptionLayer<TExternal, TDomain>bidirectional translation[AntiCorruptionLayer]attribute for HTTP clients (Refit integration)AntiCorruptionPipelineBehaviorfor automatic translation- New package planned:
Encina.AntiCorruption - Priority: HIGH - Essential for brownfield development
- Dapr Integration (Issue #387) - CNCF graduated project integration
- Dapr State Store as Outbox, Inbox, Saga store backend
- Dapr Pub/Sub as message transport
- Dapr Workflows as Saga backend alternative
- Dapr Actors integration
- New packages planned:
Encina.Dapr,Encina.Dapr.StateStore,Encina.Dapr.PubSub - Re-planned: Previously deprecated, now restored due to CNCF graduation and high community demand
- Priority: HIGH - Leading microservices framework 2025
- Virtual Actors (Orleans Integration) (Issue #388) - High concurrency pattern
IEncinaActorandIEncinaActor<TState>abstractionsEncinaGrain<TState>base class for Orleans Grains- Full Encina pipeline support within actors
- New packages planned:
Encina.Actors,Encina.Orleans - Priority: MEDIUM - Gaming, IoT, high-concurrency use cases
- API Versioning Pipeline Behavior (Issue #389) - API evolution support
[ApiVersion]attribute with deprecation supportIApiVersionContextwithCurrentVersion,IsDeprecatedIApiVersionResolverwith Header, QueryString, URL, MediaType resolversApiVersioningPipelineBehaviorfor version-aware handler routing- Priority: MEDIUM - Important for production API evolution
- Enhanced Message Deduplication (Issue #390) - Inbox pattern improvement
IDeduplicationKeyGenerator<T>for content-based keysSlidingWindowDeduplicationOptionswith Window, Strategy, CleanupDeduplicationStrategy: RejectSilently, ReturnCachedResult, ReturnError[Deduplicate]declarative attribute- Priority: MEDIUM - Improves existing Inbox functionality
- Sidecar/Ambassador Pattern Support (Issue #391) - Kubernetes-native pattern
ISidecarProxyfor Encina as sidecar processIAmbassadorProxyfor client connectivity offloadingEncinaSidecarHostBackgroundService- Kubernetes deployment examples, Docker images
- New package planned:
Encina.Sidecar - Priority: MEDIUM - Important for containerized deployments
- Event Collaboration / Process Manager (Issue #392) - Hybrid orchestration pattern
IProcessManager<TState>withHandleEventAsync,GetAuditTrailAsyncProcessManagerBase<TState>base class[CorrelateBy]attribute for event routingProcessManagerRoutingBehaviorfor automatic event dispatch- Dashboard/visibility queries
- Priority: MEDIUM - Hybrid choreography/orchestration with visibility
- Eventual Consistency Helpers (Issue #393) - Distributed systems helpers
IEventualConsistencyMonitorwithCheckAsync,WaitForConsistencyAsyncIConflictResolver<TState>with LastWriteWins, Merge, ManualResolution strategies[EventuallyConsistent]attribute withMaxLagMs,WaitForConsistencyIReadYourWritesGuaranteefor session-level consistency- Priority: LOW - Nice-to-have for complex systems
-
New labels created for Microservices patterns:
area-service-discovery- Service discovery and registry patternsarea-configuration- Configuration management and externalizationorleans-integration- Microsoft Orleans integrationdapr-integration- Dapr runtime integrationyarp-integration- Microsoft YARP reverse proxy integrationconsul-integration- HashiCorp Consul integrationaspire-integration- .NET Aspire integrationkubernetes-native- Kubernetes-native patterns and deploymentpattern-sidecar- Sidecar and Ambassador patternspattern-bff- Backend for Frontend pattern
Security Patterns Issues (8 new features planned based on December 29, 2025 research)
-
Core Security Abstractions (Issue #394) - Foundational security pattern
ISecurityContextwith CurrentPrincipal, Permissions, Roles, ClaimsIPermissionEvaluator<TResource>for dynamic permission evaluationSecurityPipelineBehaviorwith[Authorize],[RequirePermission],[RequireRole]attributes- RBAC, ABAC, Permission-based authorization support
- New package planned:
Encina.Security - Priority: CRITICAL - Foundation for all security patterns
- Audit Trail Logging (Issue #395) - Compliance-ready audit logging
IAuditLoggerwith who/what/when/where trackingAuditPipelineBehaviorfor automatic capture[Auditable]attribute with None, Minimal, Standard, Detailed levels- Storage backends: Database, Elasticsearch, Azure Table Storage, CloudWatch
- Sensitive data redaction
- New package planned:
Encina.Security.Audit - Priority: CRITICAL - Required for SOX, HIPAA, GDPR, PCI compliance
- Field-Level Encryption (Issue #396) - Data protection at rest
IFieldEncryptorwith encrypt/decrypt/rotate key operations[Encrypt]attribute for sensitive propertiesEncryptionPipelineBehaviorfor automatic encrypt/decrypt- Key rotation with versioning, Azure Key Vault/AWS KMS integration
- Crypto-shredding for GDPR (delete key = "forget" data)
- New package planned:
Encina.Security.Encryption - Priority: HIGH - PCI-DSS, GDPR sensitive data protection
- PII Masking (Issue #397) - Personal data protection
IPIIMaskerwith mask/unmask/detect operations[PII]attribute with Email, Phone, SSN, CreditCard, Address typesPIIMaskingPipelineBehaviorfor automatic response masking- Auto-detection, logging redaction
- New package planned:
Encina.Security.PII - Priority: HIGH - GDPR essential
- Anti-Tampering (Issue #398) - Request integrity verification
IRequestSignerwith HMAC-SHA256/512, RSA-SHA256, ECDSA[SignedRequest]attribute for handlers requiring verificationSignatureVerificationPipelineBehavior- Timestamp validation, nonce management for replay attack prevention
- New package planned:
Encina.Security.AntiTampering - Priority: HIGH - API security for webhooks, inter-service communication
- Input Sanitization (Issue #399) - OWASP Top 10 prevention
ISanitizer<T>with sanitize/validate operations[Sanitize]attribute with Html, Sql, Command, Path, Url typesSanitizationPipelineBehaviorfor automatic input cleaning- XSS, SQL injection, command injection, path traversal prevention
- New package planned:
Encina.Security.Sanitization - Priority: HIGH - OWASP Top 10 prevention
- Secrets Management (Issue #400) - Cloud-native secrets handling
ISecretProviderwith get/set/rotate operationsSecretProviderChainfor fallback between providers- Azure Key Vault, AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager integration
- Automatic rotation, TTL caching, access auditing
- New packages planned:
Encina.Security.Secrets.* - Priority: MEDIUM - Cloud-native best practice
- ABAC Engine (Issue #401) - Advanced authorization
IAbacEnginewith evaluate(subject, resource, action, environment)- Policy DSL for access policies
AbacPipelineBehaviorfor automatic evaluation- PDP/PEP pattern, OPA integration
- New package planned:
Encina.Security.ABAC - Priority: MEDIUM - Complex enterprise authorization
-
New labels created for Security patterns:
area-security- Security patterns and authentication/authorizationowasp-pattern- Based on OWASP security best practices
-
Compliance Patterns Issues - GDPR & EU Laws (14 new features planned based on December 29, 2025 research):
- GDPR Core Abstractions (Issue #402) - Foundation for EU compliance
IDataController,IDataProcessorinterfacesRoPARegistry(Record of Processing Activities) - Art. 30GDPRCompliancePipelineBehaviorfor automatic validation- New package planned:
Encina.Compliance.GDPR - Priority: CRITICAL - Mandatory for EU operations
- Consent Management (Issue #403) - Art. 7 compliance
IConsentManagerwith request/grant/withdraw/check operations[RequireConsent("purpose")]attribute- Consent versioning, proof of consent, granular purposes
- New package planned:
Encina.Compliance.Consent - Priority: CRITICAL - Art. 7 requirement
- Data Subject Rights (Issue #404) - Arts. 15-22 implementation
IDataSubjectRightsServicefor all GDPR rights- Right of Access (Art. 15), Rectification (Art. 16), Erasure (Art. 17)
- Right to Portability (Art. 20), Restriction (Art. 18), Object (Art. 21)
- Request tracking, 30-day SLA monitoring
- New package planned:
Encina.Compliance.DataSubjectRights - Priority: CRITICAL - Fundamental GDPR rights
- Data Residency (Issue #405) - Data sovereignty enforcement
IDataResidencyEnforcerwith geo-routing[DataResidency("EU")]attribute- Multi-region database routing, SCCs validation
- Cloud provider region mapping (AWS, Azure, GCP)
- New package planned:
Encina.Compliance.DataResidency - Priority: CRITICAL - Post-Schrems II requirement
- Data Retention (Issue #406) - Storage limitation (Art. 5(1)(e))
IRetentionPolicyEnginewith automatic deletion- Legal hold support, retention reporting
- New package planned:
Encina.Compliance.Retention - Priority: HIGH
- Anonymization (Issue #407) - Art. 4(5) pseudonymization
IAnonymizerwith k-anonymity, l-diversity, differential privacy- Crypto-shredding: delete key = data "forgotten"
- New package planned:
Encina.Compliance.Anonymization - Priority: HIGH
- Breach Notification (Issue #408) - 72-hour notification (Arts. 33-34)
IBreachNotificationServicewith detection/assessment/notification- SIEM integration (Splunk, Azure Sentinel)
- New package planned:
Encina.Compliance.BreachNotification - Priority: HIGH
- DPIA Automation (Issue #409) - Art. 35 impact assessment
IDPIAServicewith risk assessment and report generation- New package planned:
Encina.Compliance.DPIA - Priority: MEDIUM
- Processor Agreements (Issue #410) - Art. 28 compliance
IProcessorAgreementServicefor DPA management- New package planned:
Encina.Compliance.ProcessorAgreements - Priority: MEDIUM
- Privacy by Design (Issue #411) - Art. 25 enforcement
IPrivacyByDesignValidator, Roslyn analyzer- New package planned:
Encina.Compliance.PrivacyByDesign - Priority: MEDIUM
- Cross-Border Transfer (Issue #412) - Chapter V compliance
ICrossBorderTransferValidatorwith SCCs, BCRs, TIA- New package planned:
Encina.Compliance.CrossBorderTransfer - Priority: MEDIUM
- Lawful Basis (Issue #413) - Art. 6 tracking
ILawfulBasisServicefor processing validation- New package planned:
Encina.Compliance.LawfulBasis - Priority: MEDIUM
- NIS2 Directive (Issue #414) - EU 2022/2555 cybersecurity
INIS2ComplianceServicefor incident reporting- New package planned:
Encina.Compliance.NIS2 - Priority: MEDIUM
- EU AI Act (Issue #415) - EU 2024/1689 AI governance
IAIActComplianceServicefor risk classification- New package planned:
Encina.Compliance.AIAct - Priority: MEDIUM
- GDPR Core Abstractions (Issue #402) - Foundation for EU compliance
-
New labels created for Compliance patterns:
area-compliance- Regulatory compliance patterns (GDPR, NIS2, AI Act)eu-regulation- Related to European Union regulationspattern-data-masking- Data masking and PII protectionpattern-consent-management- Consent management and trackingpattern-data-sovereignty- Data residency and sovereigntyarea-data-protection- Data protection and privacy features
Advanced Validation Patterns Issues (10 new features planned based on December 2025 research)
-
Source-Generated Validation (Issue #227) - Compile-time validation code generation
- Zero reflection, NativeAOT and trimming compatible
- ~1.6x faster, ~4.7x less memory (Validot benchmarks)
- Attributes:
[GenerateValidation],[NotEmpty],[Email],[Positive], etc. - New package planned:
Encina.Validation.Generators - Inspired by Validot, Microsoft Options Validation Source Generator
- Domain/Value Object Validation (Issue #228) - Always-Valid Domain Model
- Value Objects with built-in validation
- Factory methods returning
Either<EncinaError, T>for ROP - Base classes:
ValueObject<TSelf>,SingleValueObject<TSelf, TValue> - Common value objects:
Email,PhoneNumber,Url,Money,NonEmptyString - New package planned:
Encina.Validation.Domain - Inspired by Enterprise Craftsmanship, Milan Jovanovic's DDD patterns
- Consolidate ValidationPipelineBehavior (Issue #229) - Remove duplicate behaviors
- CRITICAL technical debt: Each provider has its own duplicated behavior
- Affected: FluentValidation, DataAnnotations, MiniValidator packages
- Solution: Use centralized
ValidationPipelineBehaviorfrom core - Low effort, high impact cleanup
- Enhanced Async/Cross-Field Validation (Issue #230) - Database-backed validation
- Extensions:
MustExistAsync(),MustBeUniqueAsync(),GreaterThan(x => x.OtherProperty) - Cross-field comparison validators
- Conditional validation with
WhenAsync(),UnlessAsync()
- Extensions:
- OpenAPI Schema Validation (Issue #231) - Contract-first validation
- Automatic validation against OpenAPI 3.1 schemas
- Request/Response validation
- Prevents API drift between contract and implementation
- New package planned:
Encina.Validation.OpenApi - Inspired by Zuplo, openVALIDATION
- Security-Focused Validation (Issue #232) - OWASP-compliant validation
- Prevents >90% of injection attacks (OWASP statistics)
- Allowlist validators:
AllowlistPattern(),AllowlistValues() - Injection prevention:
NoSqlInjection(),NoXss(),NoCommandInjection() - Sanitizers:
SanitizeHtml(),StripHtml(),EncodeHtml() - New package planned:
Encina.Validation.Security - Inspired by OWASP Input Validation Cheat Sheet, ASVS
- Validation Error Localization (Issue #233) - Internationalization support
- Integration with ASP.NET Core
IStringLocalizer - Built-in translations for 12+ languages
- Placeholder support:
{PropertyName},{PropertyValue}
- Integration with ASP.NET Core
- Validation Result Aggregation (Issue #234) - Multi-source validation
ValidationAggregatorbuilder for combining validators- Strategies: FailFast, CollectAll, ParallelCollectAll, ParallelFailFast
- Error source tracking and deduplication
- Zod-like Schema Builder (Issue #235) - TypeScript-inspired fluent API
- Chainable schema definitions
- Parse returns
Either<EncinaError, T> - New package planned:
Encina.Validation.Schema - Inspired by Zod (TypeScript), zod-rs (Rust)
- Two-Phase Validation Pattern (Issue #236) - Pipeline + Domain separation
- Phase 1 (Pipeline): Fast structural validation
- Phase 2 (Handler): Domain validation with repository access
- Interfaces:
IDomainValidator<TRequest>,IDomainValidatedRequest - Best practice for clean CQRS architecture
-
New label created:
area-source-generatorsfor source generator-related features
Advanced Event Sourcing Patterns Issues (13 new features planned based on December 2025 research)
-
Decider Pattern Support (Issue #320) - Functional event sourcing with pure functions
IDecider<TCommand, TEvent, TState>interface withDecide,Evolve,InitialState- Pure functions = trivial testing without mocks
- Industry best practice 2025 (Marten, Wolverine recommended)
- Aligns with Encina's Railway Oriented Programming philosophy
- Causation/Correlation ID Tracking (Issue #321) - Distributed tracing metadata
EventMetadatawith MessageId, CausationId, CorrelationId- Automatic propagation from
IRequestContext - 30-40% reduction in troubleshooting time (empirical studies)
- Integration with
Encina.OpenTelemetry
- Crypto-Shredding for GDPR (Issue #322) - GDPR Article 17 compliance
- New package planned:
Encina.Marten.GDPR [PersonalData]attribute for PII propertiesICryptoShredderwith key vault integrations (HashiCorp, Azure, AWS)- Delete encryption key = data becomes unreadable ("forgotten")
- No .NET library offers first-class GDPR support - competitive differentiator
- New package planned:
- Advanced Snapshot Strategies (Issue #323) - Beyond event-count based
SnapshotStrategyenum: EventCount, TimeInterval, BusinessBoundary, CompositeISnapshotBoundaryDetectorfor custom boundaries- Per-aggregate configuration
- Blue-Green Projection Rebuild (Issue #324) - Zero-downtime updates
IProjectionRebuildManagerwith progress tracking- Build projection in secondary schema, switch when caught up
- CLI command:
encina projections rebuild <name>
- Temporal Queries (Issue #325) - Point-in-time state reconstruction
LoadAtAsync(id, timestamp)for historical stateITemporalEventStorefor range queries- 30% improvement in debugging time
- Multi-Tenancy Event Sourcing (Issue #326) - SaaS tenant isolation
MultiTenancyMode: Conjoined, Dedicated, SchemaPerTenant- Automatic tenant filtering in repositories
ITenantManagerfor provisioning
- Event Archival and Compaction (Issue #327) - Storage management at scale
- Hot/warm/cold tiering with cloud storage (Azure Blob, S3)
- Stream compaction strategies
- Background archival service
- Bi-Temporal Modeling (Issue #328) - Transaction + Valid time
IBiTemporalEventwith ValidTime and TransactionTime- Timeline visualization for audit
- Use cases: Financial, insurance, HR
- Visual Event Stream Explorer (Issue #329) - CLI debugging tool
encina events list/show/replay/tracecommands- Projection status and lag monitoring
- Rich terminal output with Spectre.Console
- Actor-Based Event Sourcing (Issue #330) - Alternative pattern
IEventSourcedActor<TState, TCommand, TEvent>interface- Orleans/Akka-inspired concurrency model
- Automatic lifecycle management
- EventQL Preconditions (Issue #331) - Query-based constraints
IAppendPreconditioninterface- Built-in:
StreamExists,NoEventOfType<T>,ExpectedVersion - Composite with
Preconditions.All()/Any()
- Tri-Temporal Modeling (Issue #332) - Full audit trail
- Transaction + Valid + Decision time
- Use cases: Fraud detection, legal discovery
-
New labels created for Event Sourcing patterns:
area-event-sourcing- Event Sourcing patterns and infrastructurearea-gdpr- GDPR compliance and data privacypattern-decider- Decider pattern for functional event sourcingpattern-crypto-shredding- Crypto-shredding pattern for GDPR compliancepattern-blue-green- Blue-Green deployment/rebuild patternpattern-temporal-query- Temporal queries and time-travel patternpattern-snapshot- Aggregate snapshotting patternarea-archival- Event archival and cold storage patternsarea-developer-experience- Developer experience and tooling improvementsmarten-integration- Marten library integration
Advanced CQRS Patterns Issues (12 new features planned based on December 2025 market research)
-
Zero-Interface Handlers (Issue #333) - Convention-based handler discovery
- Handlers discovered by naming convention, no
IRequestHandler<,>required - Static handlers supported (
public static class CreateOrderHandler) - Reduces boilerplate and improves DDD alignment
- Inspired by Wolverine's convention-based approach
- Depends on #50 (Source Generators) for NativeAOT compatibility
- Idempotency Pipeline Behavior (Issue #334) - Lightweight deduplication
IIdempotencyStoreinterface for key trackingIdempotencyPipelineBehavior<,>for automatic verification- Cache-based storage (Redis, In-memory) for lightweight dedup
- Complements existing Inbox pattern for simpler use cases (APIs, webhooks)
- Inspired by MassTransit and Stripe patterns
- Request Timeout Behavior (Issue #335) - Per-request timeouts
[Timeout(Seconds = 30)]attribute for declarative configurationIHasTimeoutinterface for programmatic configuration- Fallback strategies: ThrowException, ReturnDefault, ReturnCached
- OpenTelemetry integration for timeout events
- Inspired by Brighter's timeout middleware
- Cursor-Based Pagination (Issue #336) - O(1) pagination helpers
ICursorPaginatedQuery<T>interfaceCursorPaginatedResult<T>with NextCursor, HasNextPageToCursorPaginatedAsync()EF Core extension- O(1) performance vs O(n) for offset pagination
- Inspired by GraphQL Cursor Connections specification
- Request Versioning (Issue #337) - Command/query upcasting
[RequestVersion(1)]attribute for versioningIRequestUpcaster<TFrom, TTo>for automatic migration- Version chains: V1 → V2 → V3 automatic upcasting
- Deprecation logging and metrics
- Inspired by Axon Framework's event upcasting
- Multi-Tenant Context Middleware (Issue #338) - Tenant isolation
ITenantResolverwith built-in implementations (Header, Subdomain, Claims, Route)TenantValidationBehaviorfor tenant validationTenantIsolationBehaviorfor isolation enforcement- EF Core global query filter integration
- Labels:
area-multitenancy,area-security,industry-best-practice
- Batch Command Processing (Issue #339) - Atomic batch operations
IBatchCommand<TCommand, TResponse>interface- Strategies: AllOrNothing, PartialSuccess, StopOnFirstError, ContinueOnError
- Batch deduplication and parallel processing options
- Inspired by MassTransit batch consumers
- Request Enrichment (Issue #340) - Auto-populate from context
[EnrichFrom(ContextProperty.UserId)]for context properties[EnrichFromClaim("claim_name")]for JWT claimsIRequestEnricher<T>,IResponseEnricher<T>interfaces- Reduces handler boilerplate
- Inspired by Wolverine middleware
- Notification Fanout Strategies (Issue #341) - Advanced delivery
- New strategies: PriorityOrdered, Throttled, Quorum, FirstSuccessful
[NotificationPriority]attribute for ordering- Dead letter handling for failed notifications
- Circuit breaker integration
- Request Composition (Issue #342) - Combine multiple queries
QueryComposer<TResult>fluent builder- Parallel execution of independent queries
- Dependency resolution for dependent queries
- Reduces API chattiness
- Inspired by GraphQL query composition
- Handler Discovery Analyzers (Issue #343) - Compile-time validation
- ENCINA001: Handler not registered
- ENCINA002: Handler naming convention mismatch
- ENCINA003: Query modifies state (anti-pattern)
- ENCINA004: Response type mismatch
- ENCINA005: Missing validator
- Automatic code fixes
- New package:
Encina.Analyzers
- Progressive CQRS Adoption Guide (Issue #344) - Documentation
- Decision tree: when to use/not use CQRS
- Adoption levels (0-4)
- Anti-patterns to avoid
- Vertical Slice Architecture integration
- Handlers discovered by naming convention, no
-
New labels created for Advanced CQRS patterns:
wolverine-inspired- Pattern inspired by Wolverine librarybrighter-inspired- Pattern inspired by Brighter libraryaxon-inspired- Pattern inspired by Axon Framework (Java)graphql-inspired- Pattern inspired by GraphQL ecosystempattern-batch-processing- Batch processing and bulk command patternpattern-request-composition- Request composition and aggregation pattern
Domain Modeling Building Blocks Issues (15 new features planned based on December 29, 2025 DDD research)
-
Value Objects Base Class (Issue #367) - Structural equality and immutability
ValueObject<T>abstract record withGetEqualityComponents()- ROP-compatible factory methods returning
Either<EncinaError, T> - Prevents "primitive obsession" anti-pattern
- Inspired by Vogen (~5M downloads demand)
- New package planned:
Encina.DomainModeling - Labels:
foundational,area-domain-modeling,aot-compatible,industry-best-practice - Rich Domain Events (Issue #368) - Domain events with metadata
DomainEventbase record implementingINotification- Properties: EventId, OccurredAtUtc, EventVersion, CorrelationId, CausationId, AggregateId, AggregateVersion
- Integrates with existing Encina pipeline and Marten event sourcing
- Labels:
foundational,area-domain-modeling,area-messaging,area-observability
- Entity Base Class (Issue #369) - Identity equality for non-aggregates
Entity<TId>with identity-based equality- Separate from
AggregateRootfor entities within aggregates - Labels:
foundational,area-domain-modeling,aot-compatible
- Provider-Agnostic AggregateRoot (Issue #370) - State-based persistence support
AggregateRoot<TId>extendingEntity<TId>with domain event collectionRaiseDomainEvent(),ClearDomainEvents(),CheckRule()methods- Works with EF Core, Dapper (not just Marten event sourcing)
- Labels:
foundational,area-domain-modeling,area-messaging
- Specification Pattern (Issue #371) - Composable query specifications
Specification<T>abstract class withToExpression()And(),Or(),Not()composition operators- New packages:
Encina.Specifications,Encina.Specifications.EntityFrameworkCore - Inspired by Ardalis.Specification (~7M downloads)
- Labels:
new-package,area-specifications,industry-best-practice
- Business Rules Validation (Issue #372) - Domain invariant validation
IBusinessRuleinterface withErrorCode,ErrorMessage,IsSatisfied()- ROP extension:
Check()returningEither<EncinaError, Unit> - Separate from input validation (FluentValidation, DataAnnotations)
- Labels:
foundational,area-domain-modeling,area-validation
- Integration Events (Issue #373) - Cross-bounded-context events
IntegrationEventbase record with schema versioningIDomainToIntegrationEventMapper<TDomain, TIntegration>interface- Bounded context isolation pattern
- Labels:
area-domain-modeling,area-modular-monolith,area-microservices
- Strongly Typed IDs (Issue #374) - Type-safe entity identifiers
StronglyTypedId<TValue>base record- Convenience classes:
GuidId,IntId,LongId,StringId - Prevents mixing
OrderIdwithCustomerIdat compile-time - Inspired by StronglyTypedId (~3M downloads)
- Labels:
foundational,area-domain-modeling,aot-compatible
- Soft Delete Pattern (Issue #375) - Logical deletion with auto-filtering
ISoftDeletableinterface withIsDeleted,DeletedAtUtc,DeletedBy- EF Core global query filter extension
- Pipeline behavior for query filtering
- Labels:
area-auditing,area-domain-modeling,area-gdpr,area-compliance
- Auditing Pattern (Issue #376) - Created/Modified tracking
IAuditedinterface with CreatedAtUtc/By, LastModifiedAtUtc/By- EF Core SaveChanges interceptor for auto-population
- Uses
IRequestContext.UserId - Labels:
area-auditing,area-domain-modeling,area-compliance,area-security
- Domain Service Marker (Issue #377) - Semantic interface for domain services
IDomainServicemarker interface- Auto-registration extension method
- Labels:
area-domain-modeling,aot-compatible
- Anti-Corruption Layer (Issue #378) - External system isolation
IAntiCorruptionTranslator<TExternal, TDomain>interfaceIBidirectionalTranslator<,>for two-way translation- Labels:
area-domain-modeling,area-integration,area-microservices
- Bounded Context Helpers (Issue #379) - Context mapping
BoundedContextbase class withConfigure()ContextMapfor documenting context relationships- Integration with existing
IModulesystem - Labels:
area-domain-modeling,area-modular-monolith,area-architecture-testing
- Generic Repository (Issue #380) - Provider-agnostic repository abstraction
IRepository<TAggregate, TId>with CRUD operationsIRepositoryWithSpecification<,>for specification queries- Note: Controversial pattern - many prefer DbContext directly
- Labels:
area-domain-modeling,area-specifications
- Domain DSL Helpers (Issue #381) - Fluent domain builders
AggregateBuilder<TAggregate, TId, TBuilder>with rule validation- Fluent extensions for ubiquitous language
- Common domain types:
Quantity,Percentage,DateRange - Labels:
area-domain-modeling,aot-compatible
-
New labels created for Domain Modeling patterns:
area-domain-modeling- Domain modeling building blocks (Entities, Value Objects, Aggregates)area-specifications- Specification pattern for composable queriesarea-auditing- Auditing, change tracking, and soft delete patterns (already existed)foundational- Core building block that other features depend on
Vertical Slice Architecture Patterns Issues (12 new features planned based on December 29, 2025 research)
-
Feature Flags Integration (Issue #345) - Microsoft.FeatureManagement integration
[FeatureFlag("NewCheckoutFlow")]attribute for handlersFeatureFlagPipelineBehavior<,>for automatic verification- Built-in filters: Percentage, TimeWindow, Targeting, Contextual
- New package planned:
Encina.FeatureFlags - Labels:
area-feature-flags,saas-essential,industry-best-practice,aot-compatible - Multi-Tenancy Support (Issue #346) - Comprehensive SaaS multi-tenant patterns
ITenantResolverwith implementations (Header, Subdomain, Claim, Route, QueryString)TenantResolutionPipelineBehaviorandTenantIsolationPipelineBehavior- Database strategies: DatabasePerTenant, SchemaPerTenant, SharedDatabase
- EF Core query filter integration
- New packages planned:
Encina.MultiTenancy,Encina.MultiTenancy.EntityFrameworkCore - Labels:
area-multi-tenancy,saas-essential,area-security
- Specification Pattern Integration (Issue #347) - Composable query specifications
Specification<T>base class withAnd(),Or(),Not()compositionQuerySpecification<T>with includes, ordering, pagingISpecificationEvaluator<T>for EF Core and Dapper- New packages planned:
Encina.Specification,Encina.Specification.EntityFrameworkCore - Inspired by Ardalis.Specification
- API Versioning Integration (Issue #348) - Handler-level API versioning
[ApiVersion("1.0")]attribute for versioned handlersVersionedRequestDispatcherfor automatic routing- Deprecation headers: Deprecation, Sunset, Link
- New package planned:
Encina.AspNetCore.Versioning
- Request Batching / Bulk Operations (Issue #349) - Batch processing for DDD
BatchCommand<TCommand, TResponse>andBatchQuery<,>wrappers- Strategies: AllOrNothing, PartialSuccess, StopOnFirstError, ParallelAll
- Fluent
BatchBuilder<,>API - New package planned:
Encina.Batching
- Domain Events vs Integration Events (Issue #350) - Clear separation (DDD best practice)
IDomainEvent(in-process) vsIIntegrationEvent(cross-boundary)IDomainEventDispatcherwith configurable timing (BeforeCommit, AfterCommit)IIntegrationEventPublisherusing Outbox patternAggregateRoot<TId>base class with domain event collection- EF Core
DomainEventDispatchingInterceptor
- Audit Trail Pipeline Behavior (Issue #351) - Compliance and auditing
[Auditable],[NotAuditable]attributesIAuditStorewith EF Core, Dapper, Elasticsearch implementations- Sensitive data redaction with
ISensitiveDataRedactor - New packages planned:
Encina.Auditing,Encina.Auditing.EntityFrameworkCore - Labels:
area-auditing,area-gdpr,area-compliance
- Modular Monolith Support (Issue #352) - Architecture pattern 2025
EncinaModulebase class with lifecycle hooksIModuleEventBusfor inter-module communicationModuleIsolationPipelineBehaviorfor boundary enforcement- Database isolation strategies: SharedDatabase, SchemaPerModule
- New package planned:
Encina.Modules - Inspired by Milan Jovanovic, kgrzybek/modular-monolith-with-ddd
- CDC Integration (Issue #353) - Change Data Capture patterns
IChangeDataHandler<T>for entity change handling- Providers: SQL Server CDC, PostgreSQL Logical Replication, Debezium/Kafka
- New packages planned:
Encina.CDC,Encina.CDC.SqlServer,Encina.CDC.Debezium
- Enhanced Streaming Support (Issue #354) - IAsyncEnumerable improvements
StreamCachingPipelineBehavior<,>for caching streamsStreamRateLimitingPipelineBehavior<,>for per-item rate limiting- Backpressure strategies: Block, Drop, DropOldest, Error
- Extension methods:
ToListAsync(),FirstOrDefaultAsync()
- Enhanced Idempotency (Issue #355) - Stripe-style idempotency keys
[Idempotent]attribute for handlersIIdempotencyStorewith TTL and distributed locking- ASP.NET Core middleware for X-Idempotency-Key header
- Response caching with Idempotent-Replayed header
- Policy-Based Authorization Enhancement (Issue #356) - Resource-based auth
[AuthorizeRoles],[AuthorizeClaim]shortcuts[ResourceAuthorize(typeof(Order), "Edit")]for resource-based auth- CQRS-aware default policies (Commands vs Queries)
- Pre/Post authorization processors
-
New labels created for Vertical Slice Architecture patterns:
area-feature-flags- Feature flags and feature toggles patternsarea-authorization- Authorization and access control patternsarea-streaming- Streaming and IAsyncEnumerable patternsarea-batching- Request batching and bulk operationsarea-specification- Specification pattern for queriesarea-versioning- API versioning patternsarea-auditing- Audit trail and logging patternsarea-domain-events- Domain events and integration eventssaas-essential- Essential pattern for SaaS applications
Modular Monolith Architecture Patterns Issues (10 new features planned based on December 29, 2025 research)
-
Multi-Tenancy Support (Issue #357) - Comprehensive SaaS multi-tenant patterns
ITenantContextwith CurrentTenantId, CurrentTenantName, IsHostITenantResolverimplementations: Header, Subdomain, QueryString, Route, Claim, CookieDataIsolationLevelenum: RowLevel, Schema, DatabaseTenantContextPipelineBehaviorfor automatic tenant propagation- EF Core integration with automatic
TenantQueryFilter - New packages planned:
Encina.MultiTenancy,Encina.MultiTenancy.EntityFrameworkCore,Encina.MultiTenancy.AspNetCore - Labels:
area-multitenancy,area-data-isolation,saas-enabler,cloud-azure,cloud-aws - Inspired by ABP Framework, Milan Jovanović
- Inter-Module Communication (Issue #358) - Integration Events pattern
IDomainEvent : INotificationfor in-process, synchronous eventsIIntegrationEvent : INotificationwith EventId, OccurredAtUtc, SourceModuleIIntegrationEventBusfor in-memory inter-module communicationIModulePublicApi<TModule>for module public contracts- Optional Outbox integration for reliability
- Labels:
area-messaging,area-microservices,area-ddd,industry-best-practice - Inspired by Microsoft Domain Events, Milan Jovanović
- Data Isolation per Module (Issue #359) - Module boundary enforcement
ModuleDataIsolationenum: None, SeparateSchema, SeparateDatabase[ModuleSchema("orders")]attribute for module schema declarationIModuleDbContext<TModule>interface- Roslyn analyzer
ModuleDataIsolationAnalyzerwith rules:- ENC001: Cross-module DbContext access detected
- ENC002: Direct table reference to another module's schema
- ENC003: JOIN across module boundaries
- Runtime query boundary enforcement
- New packages planned:
Encina.Modular.Data,Encina.Modular.Data.Analyzers - Labels:
area-data-isolation,roslyn-analyzer,area-architecture-testing - Inspired by Milan Jovanović Data Isolation patterns
- Module Lifecycle Enhancement (Issue #360) - Orleans/NestJS-inspired module system
- Automatic module discovery:
DiscoverModulesFromAssemblies(),DiscoverModulesFromPattern() [DependsOn(typeof(OtherModule))]for dependency declaration- Topological sort for startup order
- Expanded lifecycle hooks: OnModulePreConfigure, Configure, PostConfigure, Initialize, Started, Stopping, Stopped
- Module exports (NestJS-inspired):
public override Type[] Exports ModuleGraphfor visualization/debugging- Labels:
area-module-system,area-pipeline,industry-best-practice - Inspired by Orleans Lifecycle, NestJS Modules
- Automatic module discovery:
- Feature Flags Integration (Issue #361) - Microsoft.FeatureManagement integration
[FeatureGate("FeatureName")]attribute for handlersFeatureGatePipelineBehaviorwith short-circuit on disabled feature[FallbackHandler]for fallback when feature is off- Per-tenant feature flags with
[TenantFeatureFilter] - Azure App Configuration support
- New packages planned:
Encina.FeatureManagement,Encina.FeatureManagement.AspNetCore - Labels:
area-feature-flags,saas-enabler,cloud-azure
- Module Testing Utilities (Issue #362) - Encina.Testing extensions
ModuleTestBase<TModule>base class for isolated module testingWithMockedModule<TApi>()for mocking module dependenciesIntegrationEvents.ShouldContain<TEvent>()assertionsModuleArchitecture.Analyze()for architecture testingModuleDataArchitecturefor data isolation tests- Given/When/Then helpers for saga testing
- Labels:
area-testing,area-architecture-testing,testing-integration - Inspired by ArchUnitNET, NetArchTest
- Anti-Corruption Layer Support (Issue #363) - DDD pattern
IAntiCorruptionLayer<TExternal, TInternal>interfaceIAsyncAntiCorruptionLayer<,>for complex async translations[ModuleAdapter(From, To)]for inter-module adapters[ExternalSystemAdapter("LegacyERP")]for external systemsAntiCorruptionPipelineBehaviorfor automatic translation- Auto-discovery of adapters
- Labels:
area-acl,area-ddd,area-interop,area-microservices - Inspired by Azure ACL Pattern
- Module Health & Readiness (Issue #364) - Cloud-native module health
IModuleHealthCheckfor per-module health checksIModuleReadinessCheckfor readiness probesModuleHealthCheckBaseabstract class- Dependency-aware health propagation
- ASP.NET Core integration:
AddEncinaModuleHealthChecks() - Per-module endpoints:
/health/{moduleName} - Labels:
area-health-checks,area-cloud-native,cloud-aws,cloud-azure
- Vertical Slice Architecture Support (Issue #365) - VSA formalization
[VerticalSlice("Orders/PlaceOrder")]attribute[SlicePipeline(...)]for slice-scoped behaviors- Feature folder convention:
Features/{Domain}/{Slice}/ - CLI generator:
encina generate slice SliceTestBase<TSlice>for isolated testing- Labels:
area-vertical-slice,area-cli,industry-best-practice - Inspired by Jimmy Bogard VSA
- Module Versioning (Issue #366) - API evolution for modules
[ModuleVersion("2.0")]attribute[ModuleApiVersion]for versioned public APIs[Deprecated("message", RemovalVersion = "3.0")]with warningsIModuleVersionAdapter<TFrom, TTo>for version bridging- Roslyn analyzer for deprecated API usage (ENC010)
- Version compatibility validation at startup
- Labels:
area-versioning,roslyn-analyzer,area-openapi
-
New labels created for Modular Monolith patterns:
area-modular-monolith- Modular Monolith architecture patternsarea-data-isolation- Data isolation and schema separationarea-acl- Anti-Corruption Layer patternsarea-vertical-slice- Vertical Slice Architecture patternsarea-module-system- Module system, lifecycle, and discoverysaas-enabler- Enables SaaS application developmentroslyn-analyzer- Requires Roslyn analyzer implementation
Advanced Messaging Patterns Issues (15 new features planned based on market research)
- Message Batching (Issue #121) - Process multiple messages in a single handler invocation
- Inspired by Wolverine 4.0's batch handler support
- Time-based, count-based, and size-based batching modes
- Integration with Outbox/Inbox patterns
- Claim Check Pattern (Issue #122) - External storage for large message payloads
- Store large payloads in Azure Blob, S3, or FileSystem
- Pass only reference through message broker
- Reduces messaging costs and improves throughput
- New packages planned:
Encina.ClaimCheck,Encina.ClaimCheck.AzureBlob,Encina.ClaimCheck.AmazonS3
- Message Priority (Issue #123) - Priority-based message processing
- Process high-priority messages before lower-priority ones
- Anti-starvation mechanisms for fairness
- Enhanced Deduplication (Issue #124) - Multiple deduplication strategies
- MessageId, ContentHash, TimeWindow, IdempotencyKey strategies
- Extends current Inbox pattern capabilities
- Multi-Tenancy Messaging (Issue #125) - First-class SaaS tenant isolation
- Automatic TenantId propagation in message context
- Tenant-isolated stores (Outbox, Inbox, Saga)
- Per-tenant configuration and rate limits
- Message TTL (Issue #126) - Time-to-live and automatic expiration
- Prevents processing stale data
- Integration with Dead Letter Queue
- Request/Response RPC (Issue #127) - RPC-style messaging
- Synchronous-style communication over message brokers
- Correlation ID management and timeout handling
- Saga Visibility (Issue #128) - Enhanced saga observability
- Query APIs for saga state
- Step history and audit trail
- Metrics for in-flight, completed, and failed sagas
- Message Encryption (Issue #129) - Compliance-ready encryption
- Transparent encryption/decryption in Outbox/Inbox
- Multiple providers: Azure Key Vault, AWS KMS, Data Protection
- GDPR, HIPAA, PCI-DSS compliance support
- New packages planned:
Encina.Encryption,Encina.Encryption.AzureKeyVault,Encina.Encryption.AwsKms
- Competing Consumers (Issue #130) - Consumer group management
- Consumer group registration and rebalancing
- Partition assignment strategies
- Kubernetes-native scaling support
- Backpressure & Flow Control (Issue #131) - Overload protection
- Producer rate limiting
- Queue depth monitoring
- Adaptive concurrency control
- W3C Trace Context (Issue #132) - OpenTelemetry context propagation
- Full W3C Trace Context support (traceparent, tracestate)
- Baggage propagation for custom metadata
- Activity integration for handlers
- Recurring Messages (Issue #133) - Cron-style scheduling
- Cron expression support with timezone handling
- Missed occurrence strategies
- Extends current Scheduling pattern
- Message Versioning (Issue #134) - Schema evolution with upcasting
- Version stamps on messages
- Upcaster registry for automatic transformation
- Zero-downtime deployments
- Poison Message Detection (Issue #135) - Intelligent poison message handling
- Automatic classification (transient, permanent, malformed)
- Per-classification actions (retry, DLQ, quarantine)
- Security violation alerting
Database Providers Patterns Issues (16 new features planned based on December 2025 research)
-
Generic Repository Pattern (Issue #279) - Unified data access abstraction
IRepository<TEntity, TId>with GetByIdAsync, AddAsync, UpdateAsync, DeleteAsync, ListAsyncIReadRepository<TEntity, TId>for CQRS scenarios- Implementations for EF Core, Dapper, MongoDB
- Inspired by Ardalis.Specification
- Specification Pattern (Issue #280) - Reusable query encapsulation
ISpecification<T>with Criteria, Includes, OrderBy, PagingSpecification<T>base class with fluent API- Provider-specific evaluators (EF Core LINQ, Dapper SQL, MongoDB FilterDefinition)
- Unit of Work Pattern (Issue #281) - Cross-aggregate transactions
IUnitOfWorkwith SaveChangesAsync, BeginTransactionAsync, CommitAsync, RollbackAsync- Repository factory method for transactional consistency
- Multi-Tenancy Database Support (Issue #282) - SaaS tenant isolation
- Strategies: Shared Schema, Schema-per-Tenant, Database-per-Tenant
- Tenant resolvers: Header, Subdomain, JWT Claim, Route
- New packages planned:
Encina.Tenancy,Encina.Tenancy.SharedSchema, etc.
- Read/Write Database Separation (Issue #283) - CQRS physical split
IReadWriteDbContextFactory<TContext>for read replica routing- Automatic routing based on IQuery/ICommand
- Azure SQL ApplicationIntent=ReadOnly support
- Bulk Operations (Issue #284) - High-performance data operations
IBulkOperations<TEntity>: BulkInsertAsync, BulkUpdateAsync, BulkDeleteAsync, BulkMergeAsync- Performance: Dapper 27-384x, EF Core 100x, ADO.NET 64-244x, MongoDB 13-112x faster
- Measured with Testcontainers (SQL Server 2022, MongoDB 7)
- Soft Delete & Temporal Tables (Issue #285) - Logical delete + history
ISoftDeletableinterface with automatic global query filterITemporalRepository<TEntity, TId>for SQL Server temporal tables- Queries: GetAsOfAsync, GetHistoryAsync, GetChangedBetweenAsync
- Audit Trail Pattern (Issue #286) - Change tracking
IAuditableEntitywith CreatedAtUtc, CreatedBy, ModifiedAtUtc, ModifiedByAuditInterceptorfor automatic population via IRequestContext.UserId- TimeProvider integration for testable timestamps
- Optimistic Concurrency Abstractions (Issue #287) - Conflict resolution
IConcurrencyAware(RowVersion) andIVersioned(integer version)IConcurrencyConflictResolver<TEntity>: ClientWins, DatabaseWins, Merge strategiesIConcurrentRepository<TEntity, TId>with retry support
- CDC Integration (Issue #288) - Change Data Capture
ChangeEvent<T>with Operation, Before, After, MetadataICDCConsumer<T>,ICDCSubscriptionManagerinterfaces- New packages planned:
Encina.CDC,Encina.CDC.Debezium - Complements Outbox for legacy system integration
- Database Sharding Abstractions (Issue #289) - Horizontal partitioning
IShardable,IShardRouter<TEntity>,IShardedRepository<TEntity, TId>- Strategies: Hash (consistent hashing), Range, Directory, Geo
- Scatter-Gather for cross-shard queries
- Connection Pool Resilience (Issue #290) - Pool monitoring and health
IDatabaseHealthMonitorwith ConnectionPoolStats- Database-aware circuit breaker, connection warm-up
- Integration with Encina.Extensions.Resilience
- Query Cache Interceptor (Issue #291) - EF Core second-level cache
IDbCommandInterceptorfor automatic query result caching- Automatic invalidation on SaveChanges
- Integration with existing ICacheProvider
- Domain Entity Base Classes (Issue #292) - DDD foundations
Entity<TId>with equality and domain events collectionAggregateRoot<TId>with audit + concurrency traitsDomainEventDispatcherSaveChanges interceptor
- Pagination Abstractions (Issue #293) - Standardized paging
PagedResult<T>with TotalCount, TotalPages, HasNext/PreviousPaginationOptions,SortedPaginationOptionsIPagedSpecification<T>integration
- Cursor-based Pagination (Issue #294) - Keyset pagination research
- O(1) performance vs offset O(n) for large datasets
- GraphQL Relay Connection spec compatible
- Use cases: Infinite scroll, real-time feeds, public APIs
-
New labels created (10) for database patterns:
area-repository- Repository pattern and data access abstractionsarea-unit-of-work- Unit of Work and transaction patternsarea-cqrs- CQRS and read/write separation patternsarea-bulk-operations- Bulk insert, update, delete operationsarea-audit- Audit trails and change trackingarea-cdc- Change Data Capture patternsarea-sharding- Database sharding and horizontal partitioningarea-pagination- Pagination patterns (offset, cursor, keyset)area-concurrency- Concurrency control and conflict resolutionarea-connection-pool- Connection pooling and management
Advanced DDD & Workflow Patterns Issues (13 new features planned based on December 29, 2025 research)
-
Specification Pattern (Issue #295) - Query composition with reusable specifications
ISpecification<T>with Criteria, Includes, OrderBy, PagingSpecification<T>base class with fluent builder- AND/OR/NOT composition operators
- Provider evaluators for EF Core and Dapper
- Inspired by Ardalis.Specification
- Labels:
pattern-specification,area-ddd,area-repository,industry-best-practice - Process Manager Pattern (Issue #296) - Dynamic workflow orchestration
IProcessManager<TData>withProcessDecisiontypes- Dynamic routing vs predefined Saga sequences
- Background processor for process advancement
- Inspired by Enterprise Integration Patterns
- Labels:
pattern-process-manager,area-workflow,area-eip,masstransit-inspired
- State Machine Pattern (FSM) (Issue #297) - Fluent state machine for entity lifecycle
StateMachineBuilder<TState, TTrigger>fluent API- Entry/exit actions, substates, guards
- External state accessor for ORM integration
- DOT graph export for visualization
- Inspired by Stateless library (6k+ stars) and MassTransit Automatonymous
- Labels:
pattern-state-machine,area-saga,area-workflow,masstransit-inspired
- Claim Check Pattern (Issue #298) - Large payload handling
IClaimCheckStorefor external payload storage[ClaimCheck]attribute with threshold and expiryClaimCheckPipelineBehaviorfor automatic handling- Providers: Azure Blob, S3, File System, In-Memory
- Classic Enterprise Integration Pattern
- Labels:
pattern-claim-check,area-eip,area-messaging,area-scalability
- Anti-Corruption Layer (ACL) (Issue #299) - Domain protection from external APIs
IAntiCorruptionLayer<TExternal, TInternal>interfaceAntiCorruptionLayerBehaviorfor automatic translationIExternalEventTranslatorfor integration events- Core DDD pattern by Eric Evans
- Labels:
pattern-acl,area-ddd,area-integration,industry-best-practice
- Feature Flag Integration (Issue #300) - Microsoft.FeatureManagement pipeline
[FeatureGate]attribute with behavior optionsFeatureFlagPipelineBehaviorfor short-circuit- Contextual targeting via IRequestContext
- Use cases: dark deployments, canary releases, A/B testing
- Labels:
pattern-feature-flags,area-feature-management,cloud-azure
- Priority Queue Support (Issue #301) - Priority-based message processing
MessagePriorityenum (Critical, High, Normal, Low, Background)[MessagePriority]attribute for requests- Priority-aware batch fetching in Outbox and Scheduling
- Labels:
area-messaging,area-scheduling,area-scalability
- Batching/Bulk Operations (Issue #302) - Batch handler pattern
IBatchHandler<TRequest, TResponse>interfaceBatchingPipelineBehaviorwith auto-batching[BatchOptions]with MaxBatchSize, MaxDelayMs- Failure strategies: Individual, FailAll, RetryFailed
- Labels:
area-bulk-operations,area-messaging,area-performance
- Durable Execution / Checkpointing (Issue #303) - Long-running workflow support
IDurableContextwith ExecuteActivityAsync, WaitForEventAsync, CreateTimerAsyncIDurableWorkflow<TInput, TOutput>interface- Deterministic replay with history
- Inspired by Azure Durable Functions and Temporal.io
- Labels:
pattern-durable-execution,area-workflow,temporal-inspired,cloud-azure
- Multi-Tenancy Pipeline Behavior (Issue #304) - Automatic tenant isolation
ITenantScopedQuery/Commandmarker interfacesTenantIsolationPipelineBehaviorfor enforcement- EF Core global query filter extension
[AllowCrossTenant]for admin scenarios- Labels:
area-multi-tenancy,area-security,area-compliance,industry-best-practice
- AI Agent Orchestration (Issue #305) - LLM agent coordination (Future)
IAgentHandler<TRequest, TResponse>with capabilities- Orchestration patterns: Sequential, Concurrent, Handoff
- Semantic Kernel adapter
- Inspired by Microsoft Agent Framework (Oct 2025)
- Labels:
area-ai-ml,area-workflow,new-package
- Integration Events (Issue #306) - Modular Monolith inter-module events
IIntegrationEventwith EventId, OccurredAtUtc, SourceModuleIModuleEventBusfor in-process publishing- Outbox integration for reliability
- Inspired by Spring Modulith 2.0
- Labels:
area-modular-monolith,area-messaging,area-microservices
- Request Versioning Pattern (Issue #307) - Request evolution and upcasting
[RequestVersion]andIUpgradableFrom<T>interfacesRequestVersioningBehaviorfor auto-upgrade[DeprecatedRequest]with warnings- Inspired by Marten Event Upcasting
- Labels:
pattern-versioning,area-messaging,area-event-sourcing
-
New labels created (12) for DDD & Workflow patterns:
pattern-specification- Specification pattern for query compositionpattern-process-manager- Process Manager workflow orchestrationpattern-state-machine- Finite State Machine patternpattern-claim-check- Claim Check pattern for large payloadspattern-acl- Anti-Corruption Layer patternpattern-feature-flags- Feature Flags/Toggles patternpattern-durable-execution- Durable Execution and checkpointingpattern-versioning- Request/Event versioning patternarea-feature-management- Feature flag managementarea-workflow- Workflow and process orchestrationtemporal-inspired- Pattern inspired by Temporal.iomasstransit-inspired- Pattern inspired by MassTransit
Advanced EDA Patterns Issues (12 new features planned based on December 29, 2025 research)
-
Based on analysis of MassTransit, Wolverine 5.0, Temporal.io, Axon Framework, Debezium, and community demand
-
CDC (Change Data Capture) Pattern (Issue #308) - Database change streaming
ICdcConnector,IChangeEventHandler<TEntity>for insert/update/delete- New packages planned:
Encina.CDC,Encina.CDC.Debezium,Encina.CDC.SqlServer - Use case: Strangler Fig migration, legacy system integration
- Labels:
area-cdc,area-microservices,industry-best-practice,aot-compatible - Schema Registry Integration (Issue #309) - Event schema governance
ISchemaRegistrywith GetSchema, RegisterSchema, CheckCompatibility- New packages planned:
Encina.SchemaRegistry,Encina.SchemaRegistry.Confluent - Supports Avro, Protobuf, JsonSchema formats
- Labels:
area-schema-registry,transport-kafka,area-compliance,industry-best-practice
- Event Mesh / Event Gateway (Issue #310) - Enterprise event distribution
IEventMesh,IEventGatewayfor cross-transport routing- New packages planned:
Encina.EventMesh,Encina.EventMesh.CloudEvents - Cross-transport: Kafka → RabbitMQ → Azure Service Bus
- Labels:
area-cloud-native,area-integration,industry-best-practice
- Claim Check Pattern (Issue #311) - Large payload external storage
IClaimCheckStorewith Store/Retrieve/Delete andClaimTicket- New packages planned:
Encina.ClaimCheck,Encina.ClaimCheck.AzureBlob,Encina.ClaimCheck.S3 [ClaimCheck]attribute with ThresholdBytes- Labels:
area-eip,area-performance,cloud-azure,cloud-aws
- Domain vs Integration Events (Issue #312) - Clear event type separation
IDomainEvent(in-process),IIntegrationEvent(cross-service)IEventTranslator<TDomain, TIntegration>for Anti-Corruption Layer- Core DDD pattern for bounded context isolation
- Labels:
area-ddd,area-event-sourcing,area-modular-monolith,area-microservices
- Event Correlation & Causation Tracking (Issue #313) - Full event traceability
IEventMetadatawith EventId, CorrelationId, CausationId, TimestampEventCorrelationPipelineBehaviorfor automatic propagation- OpenTelemetry integration with span tags
- Labels:
area-observability,netflix-pattern,industry-best-practice
- Temporal Queries (Time Travel) (Issue #314) - Point-in-time state queries
ITemporalRepository<T>with GetAt(pointInTime), GetAtVersion, GetHistoryAggregateDiff<T>for state comparison- Use case: Auditing, debugging, what-if scenarios
- Labels:
area-event-sourcing,area-compliance,industry-best-practice
- Durable Execution / Workflow Engine (Issue #315) - Lightweight Temporal.io-style
IDurableWorkflow<TInput, TOutput>,IWorkflowContext,IWorkflowRunner- Activities, durable timers, signals, deterministic replay
- New packages planned:
Encina.DurableExecution,Encina.DurableExecution.EntityFrameworkCore - Labels:
area-workflow,temporal-pattern,uber-pattern,netflix-pattern
- Event Enrichment Pipeline (Issue #316) - Batch enrichment for projections
IEventEnricher<T>,IBatchEventEnricherfor N+1 avoidanceEnrichmentContextwith StreamId, Version, Services- Inspired by Marten 4.13 EnrichEventsAsync
- Labels:
area-event-sourcing,area-performance,area-pipeline
- Process Manager Pattern (Issue #317) - Long-running aggregate coordination
IProcessManager<TState>,ProcessManagerBase<TState>- Event-driven coordination vs Saga's predefined sequences
IProcessManagerStorefor persistence- Labels:
area-saga,area-event-sourcing,area-coordination
- Event Streaming Abstractions (Issue #318) - First-class event streams
IEventStreamPublisher,IEventStreamSubscription- Consumer groups, position tracking, acknowledgment
- Similar to Kafka consumer groups, RabbitMQ Streams
- Labels:
area-event-streaming,transport-kafka,transport-redis,netflix-pattern
- Idempotency Key Generator (Issue #319) - Standardized key generation
IIdempotencyKeyGeneratorwith Generate, GenerateFromParts[IdempotencyKey]attribute with Properties, Namespace, Format- Strategies: Hash (SHA256), Composite, UUID v5
- Labels:
area-idempotency,stripe-pattern,uber-pattern,netflix-pattern
-
New labels created (6) for EDA patterns:
area-schema-registry- Schema Registry and event schema governancearea-event-streaming- Event streaming and persistent log patternsarea-idempotency- Idempotency and exactly-once processinguber-pattern- Pattern inspired by Uber engineeringstripe-pattern- Pattern inspired by Stripe engineeringtemporal-pattern- Pattern inspired by Temporal.io
Advanced Caching Patterns Issues (13 new features planned based on December 2025 research)
-
Cache Stampede Protection (Issue #266) - Thundering herd prevention with multiple strategies
- Inspired by FusionCache (most popular .NET caching library 2025)
- Single-Flight pattern: Coalesce concurrent requests into one factory execution
- Probabilistic Early Expiration (PER): Renew cache before expiration probabilistically
- TTL Jitter: Add random variation to prevent synchronized expiration
- Labels:
pattern-stampede-protection,area-resilience,area-performance - Eager Refresh / Background Refresh (Issue #267) - Proactive cache refresh
- Inspired by FusionCache's EagerRefreshThreshold
- Refresh in background before TTL expires (e.g., after 80% of duration)
- Users always get cached response, fresh data arrives asynchronously
- Eliminates latency spikes from cache expiration
- Fail-Safe / Stale-While-Revalidate (Issue #268) - Resilient caching
- Serve stale data when factory fails or is slow
- Soft/Hard timeout support: Return stale immediately if factory exceeds threshold
- FailSafeDurationSeconds: Extended TTL for emergency use
- Fail-safe throttling to prevent retry storms
- Cache Warming / Pre-warming (Issue #269) - Cold cache elimination
ICacheWarmerinterface for custom warmers[CacheWarmer]attribute for automatic query warming- Startup warming via
CacheWarmingHostedService - Configurable strategies: Sequential, Parallel, TopHeavy
- Cache Backplane (Issue #270) - Multi-node synchronization
ICacheBackplaneinterface for L1 cache sync across instances- Redis backplane implementation with Pub/Sub
- Modes: InvalidationOnly, SmallValueReplication, FullReplication
- Node coordination and health tracking
- Enhanced Tag-Based Invalidation (Issue #271) - Semantic cache grouping
Tagsproperty on[Cache]attribute[CacheTag]attribute for dynamic tags from responseRemoveByTagAsynconICacheProvider- More efficient than pattern-based invalidation (O(1) vs scan)
- Read-Through / Write-Through Patterns (Issue #272) - Alternative caching strategies
CacheStrategyenum: CacheAside, ReadThrough, WriteThrough, WriteBehind- Read-Through: Cache as primary data source
- Write-Through: Synchronous write to cache + database
- Write-Behind: Async persistence with batching
- Cache Metrics OpenTelemetry (Issue #273) - Comprehensive observability
- Counters: hits, misses, sets, removals, evictions
- Histograms: latency, value size
- Gauges: size_bytes, entry_count, hit_rate
- Resilience: stampede_prevented, stale_served, backplane_messages
- Advanced Serialization (Issue #274) - Performance optimization
- Per-type serializer configuration
- MemoryPack support (NativeAOT, ~10x faster than MessagePack)
- Zstd compression (better ratio than LZ4)
- Smart compression based on payload size
- Multi-Tenant Cache Policies (Issue #275) - SaaS support
CacheTenantPolicyper tier (premium, standard, free)- Quotas: MaxEntries, MaxMemoryMb, DefaultDuration
- Rate limiting per tenant
- Tenant isolation levels: KeyPrefix, Database, Instance
- Cache Diagnostics & Debugging (Issue #276) - Development tooling
- HTTP headers: X-Cache-Status, X-Cache-Key, X-Cache-Age, X-Cache-TTL
- Diagnostic endpoints: /cache/stats, /cache/keys, /cache/key/{key}
ICacheInspectorAPI for programmatic access- Cache debugger middleware (?cache-debug=true)
- New Cache Providers (Issue #277) - Expanded ecosystem
Encina.Caching.Memcached- Pure Memcached supportEncina.Caching.MemoryPack- AOT-friendly serializationEncina.Caching.Pogocache- New 2025 cache (evaluate when stable)
- Auto-Recovery / Self-Healing (Issue #278) - Automatic resilience
- Retry logic with exponential backoff
- Circuit breaker for cache operations
- Automatic reconnection with
ICacheConnectionManager - Fallback strategies: SkipCache, UseLocalMemory, UseSecondaryProvider
- Self-healing backplane (auto-resubscribe, clear L1 on reconnect)
-
New pattern labels created for caching:
pattern-stampede-protection- Cache stampede and thundering herd protectionpattern-stale-while-revalidate- Stale-While-Revalidate caching patternpattern-read-through- Read-Through caching patternpattern-write-through- Write-Through caching patternpattern-cache-aside- Cache-Aside caching patternpattern-backplane- Cache backplane synchronization patternpattern-circuit-breaker- Circuit Breaker resilience patternfustioncache-inspired- Pattern inspired by FusionCache library
-
Issue #140 (Cache Stampede Prevention) closed as duplicate of #266 (more comprehensive)
Advanced Resilience Patterns Issues (9 new features planned based on 2025 research)
- Hedging Pattern (Issue #136) - Parallel redundant requests for latency reduction
- Inspired by Polly v8 and Istio service mesh
- Configure parallel requests with first-response-wins semantics
- Latency percentile-based triggering (P95, P99)
- Integration with OpenTelemetry for observability
- Fallback / Graceful Degradation (Issue #137) - Alternative responses when primary operations fail
- Inspired by Resilience4j and Polly
- Cached fallbacks, static defaults, and degraded responses
- Fallback chain with priority ordering
- Circuit breaker integration for proactive fallback
- Load Shedding with Priority (Issue #138) - Netflix/Uber-inspired priority-based request shedding
- Request priority levels: Critical, Degraded, BestEffort, Bulk
- Adaptive shedding based on system load metrics
- Integration with rate limiting and circuit breakers
- Adaptive Concurrency Control (Issue #139) - Netflix-inspired dynamic concurrency limits
- Inspired by Netflix's
concurrency-limitslibrary - AIMD (Additive Increase/Multiplicative Decrease) algorithm
- Gradient-based limit adjustment based on latency
- TCP Vegas-style congestion control for services
- Inspired by Netflix's
Cache Stampede Prevention (Issue #140)- Closed as duplicate of #266 (more comprehensive)- Probabilistic early expiration to spread load
- Cascading Timeout Coordination (Issue #141) - Timeout budget propagation across call chains
- Request deadline propagation via gRPC-style patterns
- Remaining budget calculation at each service hop
- Early termination when budget exhausted
- Health Checks Standardization (Issue #142) - Unified health checks across all providers
- Kubernetes liveness/readiness/startup probe patterns
- Consistent health check interface for all Encina providers
- Health aggregation for composite systems
- Observability-Resilience Correlation (Issue #143) - OpenTelemetry integration for resilience events
- Resilience events as OpenTelemetry spans
- Metrics for circuit breaker state, retry counts, fallback usage
- Distributed tracing context propagation through resilience policies
- Backpressure / Flow Control (Issue #144) - Reactive Streams-style backpressure for streaming
- Producer/consumer rate coordination
- Buffer overflow strategies (drop, block, latest)
- Integration with IAsyncEnumerable and stream requests
- Chaos Engineering Integration (Issue #145) - Polly Chaos strategies for fault injection testing
- Latency injection, exception injection, result manipulation
- Controlled chaos via feature flags
- Integration with testing infrastructure
Advanced Scheduling Patterns Issues (15 new features planned based on 2025 research)
- Cancellation & Update API (Issue #146) - Cancel, reschedule, or update scheduled messages
- Inspired by MassTransit, Hangfire, Temporal
CancelAsync,RescheduleAsync,UpdatePayloadAsyncmethods- Batch cancellation with filters
- Priority Queue Support (Issue #147) - Priority-based message processing
- Inspired by Meta FOQS and BullMQ
- Priority levels: Critical, High, Normal, Low, Background
- Anti-starvation with aging mechanism
- Idempotency Keys (Issue #148) - Exactly-once execution guarantee
- Inspired by Temporal, Azure Durable Functions
- User-provided idempotency keys
- Automatic duplicate detection and rejection
- Dead Letter Queue Integration (Issue #149) - DLQ for failed scheduled messages
- Integration with existing DLQ infrastructure
- Automatic move after max retries
- Inspection and replay capabilities
- Timezone-Aware Scheduling (Issue #150) - Full timezone support
- Inspired by Hangfire, Quartz.NET
- DST transition handling
- IANA timezone database support
- Rate Limiting for Scheduled (Issue #151) - Prevent burst execution
- Inspired by Meta FOQS, Redis Queue
- Per-type and global rate limits
- Token bucket algorithm
- Dependency Chains (Issue #152) - DAG-based job dependencies
- Inspired by Apache Airflow, Temporal
- Job dependencies with
DependsOn - Parallel execution of independent jobs
- Observability & Metrics (Issue #153) - OpenTelemetry integration
- Scheduling-specific spans and metrics
- Queue depth, execution latency, success/failure rates
- Grafana dashboard templates
- Batch Scheduling (Issue #154) - Efficient bulk operations
ScheduleManyAsyncfor bulk scheduling- Transactional batch support
- Optimized database operations
- Delayed Message Visibility (Issue #155) - SQS-style visibility timeout
- Inspired by Amazon SQS
- Lease-based processing
- Automatic re-queue on timeout
- Scheduling Persistence Providers (Issue #156) - Backend adapters
- Hangfire backend adapter
- Quartz.NET backend adapter
- Unified API across backends
- Execution Windows (Issue #157) - Business hours support
- Inspired by Quartz.NET, enterprise schedulers
- Business hours and maintenance windows
- Holiday calendar integration
- Schedule Templates (Issue #158) - Reusable configurations
- Named schedule templates
- Template inheritance and override
- Centralized schedule management
- Webhook Notifications (Issue #159) - External system notifications
- HTTP webhook on schedule events
- Retry with exponential backoff
- Signature verification for security
- Multi-Region Scheduling (Issue #160) - Globally distributed scheduling
- Inspired by Meta FOQS, Uber Cadence
- Leader election per region
- Cross-region coordination
Advanced Observability Patterns Issues (15 new features planned based on 2025 research)
- Real Metrics Collection (EncinaMetrics) (Issue #174) - Full IEncinaMetrics implementation
- System.Diagnostics.Metrics for zero-allocation metrics
- Histograms:
encina.request.duration,encina.handler.duration - Counters:
encina.requests.total,encina.errors.total - Gauges:
encina.active.handlers,encina.pending.outbox - Standardized tags for all metrics
- Inspired by MassTransit, Wolverine OpenTelemetry
- Correlation & Causation ID Support (Issue #175) - Request tracking across services
- CorrelationId propagation through pipeline
- CausationId for message causation chains
- Extension methods for context enrichment
- Standard headers for all transports
- Inspired by NServiceBus, MassTransit
- Baggage Propagation Utilities (Issue #176) - W3C Baggage support
- Helpers for IRequestContext baggage
- AddBaggage(), GetBaggage(), GetAllBaggage()
- Automatic propagation to handlers
- Activity.Baggage integration
- Inspired by OpenTelemetry spec, .NET Aspire
- Missing Semantic Convention Attributes (Issue #177) - OTel messaging semantics
- Complete messaging semantic attributes
- messaging.system, messaging.operation, messaging.destination
- Handler-specific attributes
- OpenTelemetry Semantic Conventions compliant
- Encina.OpenTelemetry.AzureMonitor (Issue #178) - Azure integration package
- Azure Application Insights integration
- Native Azure Monitor exporters
- Live Metrics Stream support
- Azure distributed tracing
- Encina.OpenTelemetry.AwsXRay (Issue #179) - AWS integration package
- AWS X-Ray via ADOT integration
- Native AWS exporters
- AWS Lambda instrumentation
- AWS distributed tracing
- Encina.OpenTelemetry.Prometheus (Issue #180) - Prometheus metrics package
- Native /metrics endpoint
- OpenMetrics format
- Configurable labels
- Grafana integration
- Encina.HealthChecks Package (Issue #181) - Dedicated health checks
- Kubernetes probes: liveness, readiness, startup
- Health check aggregation
- Status dashboard support
- Pattern-specific health checks
- Encina.Serilog.OpenTelemetry (Issue #182) - Serilog to OTel bridge
- Serilog → OpenTelemetry Logs export
- Automatic trace context enrichment
- Optimized formatters
- Sampling Behaviors (Issue #183) - Configurable trace sampling
- Head and tail sampling
- Probabilistic sampling
- Rate-limiting sampler
- Per-request-type sampling rules
- Request Tracing Behavior (Issue #184) - Detailed request tracing
- Per-request Activity spans
- Handler timing
- Pipeline step visibility
- Error correlation
- Error Recording Enhancements (Issue #185) - Enhanced error capture
- Exception details in spans
- Stack trace recording
- Error categorization
- OTel error semantic conventions
- Distributed Context Properties (Issue #186) - Context propagation
- Custom property propagation
- Cross-service context sharing
- W3C Trace Context extensions
- Grafana Dashboards (Issue #187) - Pre-built visualizations
- Main Encina dashboard JSON
- Per-pattern dashboards (Outbox, Saga, etc.)
- Configurable alerts
- One-click import
- Aspire Dashboard Integration Guide (Issue #188) - .NET Aspire docs
- Aspire Dashboard configuration
- Encina trace visualization
- Local development setup
Web/API Integration Patterns Issues (18 new features planned based on December 2025 research)
-
Server-Sent Events (Issue #189) - Native .NET 10 SSE support
- Leverage
TypedResults.ServerSentEventsAPI from ASP.NET Core 10 SseEndpointExtensionsfor easy endpoint registration- Heartbeat/keep-alive and automatic retry configuration
- Integration with notification streaming patterns
- Use cases: dashboards, real-time notifications, progress indicators
- REPR Pattern Support (Issue #190) - Request-Endpoint-Response pattern
EncinaEndpoint<TRequest, TResponse>abstract base classCommandEndpointandQueryEndpointspecialized variants- Fluent
EndpointBuilderfor configuration - Auto-registration via assembly scanning
- Alignment with Vertical Slice Architecture and CQRS
- Inspired by FastEndpoints and industry best practices
- Problem Details RFC 9457 (Issue #191) - Updated error response standard
- Update from RFC 7807 to RFC 9457 (supersedes 7807)
- Automatic TraceId inclusion in error responses
IExceptionHandlerimplementation for global exception handling- Timestamp and error code in extensions
- Validation problem details with proper grouping
- API Versioning Helpers (Issue #192) - Comprehensive versioning support
- Integration with
Asp.Versioning.Httppackage [ApiVersion]attribute support for handlers- Version-aware handler resolution
- Deprecation headers (Sunset RFC 8594, Deprecation)
- Multiple versioning strategies (URI, query, header, media type)
- Integration with
- Minimal APIs Organization (Issue #193) - Endpoint organization extensions
IEncinaEndpointModuleinterface for modular organizationMapEncinaModulesfor auto-registrationMapPostEncina,MapGetEncina, etc. extension methodsWithEncinaResponses()for common response documentation- Feature folder conventions support
- Encina.SignalR Package (Issue #194) - Real-time bidirectional communication
- New package:
Encina.SignalR(documented but not yet implemented) ISignalRNotificationBroadcasterfor broadcasting notificationsEncinaHubbase class with Send/Publish methods- Group management with tenant isolation
[BroadcastToSignalR]attribute for automatic broadcasting- Integration with existing notification patterns
- New package:
- GraphQL/HotChocolate Full Integration (Issue #195) - Complete GraphQL support
- Enhance existing
Encina.GraphQLfrom basic bridge to full integration - Auto-generate Query/Mutation types from handlers with
[GraphQLQuery],[GraphQLMutation] - Subscription support with pub/sub integration
- DataLoader base class for N+1 prevention
Either<EncinaError, T>→ GraphQL error mapping viaEncinaErrorFilter- RequestContext propagation to resolvers
- Enhance existing
- gRPC Improvements (Issue #196) - Strong typing and streaming
- Proto code generation from handler types
- Strongly-typed service implementations (replacing reflection-based)
- Server, client, and bidirectional streaming with
IAsyncEnumerable - Service interceptors for logging, auth, metrics
EncinaError→ gRPC Status code mapping
- Rate Limiting Pipeline Behavior (Issue #197) - Handler-level rate limiting
[RateLimit]attribute for per-handler configuration- Support for Fixed/Sliding/Token/Concurrency limiters
- Partition keys: User, Tenant, IP, ApiKey, Custom
- Response headers: X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After
- Distributed rate limiting support (Redis, SQL Server)
- Integration with ASP.NET Core rate limiting middleware
- OpenAPI 3.1 Enhanced (Issue #198) - Schema generation and SDK support
- Auto-generate OpenAPI schemas from handler types
- Data annotation → OpenAPI constraint mapping
- XML comments integration
- Encina error response documentation
- Client SDK generation helpers (NSwag, OpenAPI Generator)
- YAML export support
- BFF Pattern Support (Issue #199) - Backend for Frontend
- New package:
Encina.AspNetCore.BFF IBffAggregatorfor query aggregation- Client-specific response transformation
- Client detection (header, user-agent, claims)
- Client-aware caching
- Parallel aggregation with timeout and partial results
- New package:
- AI/LLM Integration Patterns (Issue #200) - Provider-agnostic AI integration
- New packages:
Encina.AI,Encina.AI.OpenAI,Encina.AI.Azure,Encina.AI.Anthropic,Encina.AI.Ollama,Encina.AI.SemanticKernel IAIProviderabstraction for multiple LLM providersIAIRequest<TResponse>integration with Encina pipeline- Chat completion, embedding, and structured output support
- Streaming responses via
IAsyncEnumerable - Prompt validation behavior (PII detection, injection prevention)
- Semantic Kernel adapter for orchestration
- Fallback chain for provider resilience
- New packages:
- Vertical Slice Architecture Templates (Issue #201) - CLI scaffolding
encina new feature <name>command for complete feature slices- Generate command, query, endpoint, validator, and test files
- Module registration and DI extension files
- Custom template support
- Interactive mode for guided generation
- WebHook Support (Issue #202) - Webhook receiving and sending
IWebhookHandler<TPayload>interface- Signature validation (HMAC-SHA256, HMAC-SHA1)
- Timestamp validation for replay attack prevention
- Inbox pattern integration for idempotency
- Webhook sender with retry and dead letter
- Provider configuration (Stripe, GitHub, etc.)
- Health Aggregation Endpoint (Issue #203) - Combined health checks
- Aggregated
/healthendpoint /health/readyand/health/liveseparation (Kubernetes probes)/health/detailedwith authorization- Module health check auto-discovery
- Response caching
- Aggregated
- Passkey Authentication (Issue #204) - WebAuthn/FIDO2 support
[RequirePasskey]attribute for high-security operations- Integration with .NET 10 ASP.NET Core Identity passkey features
IPasskeyChallengerfor challenge/response flow- Fallback to password option
- Google Cloud Functions (Issue #205) - GCF integration
- New package:
Encina.GoogleCloudFunctions EncinaHttpFunctionbase classEncinaCloudEventFunctionfor Pub/Sub events- Context enrichment (correlation ID, trace ID)
- Health check integration
- New package:
- Cloudflare Workers (Issue #206) - Edge computing integration
- New package:
Encina.CloudflareWorkers EncinaWorkerbase class- KV storage integration (as cache provider)
- Durable Objects for saga coordination (future)
- D1 database integration (future)
- New package:
- Leverage
-
New Labels Created (Web/API - December 2025):
area-ai-ml- AI/ML and LLM integration patternsarea-bff- Backend for Frontend patternsarea-openapi- OpenAPI/Swagger documentation and generationarea-webhooks- Webhook receiving and sending patternsarea-rate-limiting- Rate limiting and throttling patternsarea-health-checks- Health checks and readiness probesarea-authentication- Authentication patterns (Passkeys, OAuth, etc.)cloud-cloudflare- Cloudflare Workers and services
Advanced Testing Patterns Issues (13 new features planned based on 2025 research)
-
Test Data Generation (Issue #161) - Bogus/AutoBogus integration for realistic test data
EncinaFaker<T>base class with Encina-specific conventions- Pre-built fakers for messaging entities (Outbox, Inbox, Saga, Scheduled)
- Seed support for deterministic, reproducible tests
- New package planned:
Encina.Testing.DataGeneration - Testcontainers Integration (Issue #162) - Docker fixtures for database testing
- Pre-configured fixtures:
SqlServerContainerFixture,PostgreSqlContainerFixture,MongoDbContainerFixture,RedisContainerFixture - Integration with existing
EncinaFixture - GitHub Actions CI/CD compatible
- New package planned:
Encina.Testing.Testcontainers
- Pre-configured fixtures:
- Database Reset with Respawn (Issue #163) - Intelligent cleanup between tests
EncinaRespawnerfactory with Encina-specific table exclusionsDatabaseIntegrationTestBaseabstract class- 3x faster than truncate/recreate approach
- HTTP Mocking with WireMock (Issue #164) - External API mocking
EncinaWireMockFixturewith helpers:SetupOutboxWebhook(),SetupExternalApi()EncinaRefitMockFixture<TClient>for Refit clients- Fault simulation:
SetupFault(),SetupDelay() - New package planned:
Encina.Testing.WireMock
- Snapshot Testing with Verify (Issue #165) - Approval testing for complex responses
EncinaVerifyExtensionsfor Either, ValidationResult, EncinaError- Custom JSON converters for Encina types
- Data scrubbing for non-deterministic values (GUIDs, dates)
- Architecture Testing with ArchUnitNET (Issue #166) - CQRS architecture rules
EncinaArchitectureRuleswith pre-defined rulesCommandsMustNotReturnVoid(),QueriesMustNotModifyState()HandlersMustNotDependOnControllers(),DomainMustNotDependOnInfrastructure()- New package planned:
Encina.Testing.Architecture
- Handler Registration Tests (Issue #167) - Verify all handlers are registered
EncinaRegistrationAssertions.AllRequestsShouldHaveHandlers(assembly)EncinaRegistrationAssertions.AllNotificationsShouldHaveHandlers(assembly)RegistrationVerifierfluent API- Early detection of missing handler registrations
- Pipeline Testing Utilities (Issue #168) - Control behaviors in tests
PipelineTestContext<TRequest, TResponse>for pipeline testingWithBehavior<T>(),WithoutBehavior<T>(),WithMockedHandler()methodsVerifyBehaviorCalled<T>(Times)verificationPipelineTest.For<TRequest, TResponse>()factory
- Messaging Pattern Helpers (Issue #169) - Helpers for Outbox, Inbox, Saga, Scheduling
OutboxTestHelper:CaptureMessages(),VerifyMessagePublished<T>()InboxTestHelper:SimulateIdempotentMessage(),VerifyProcessedOnce()SagaTestBase<TSaga, TData>: Given/When/Then for sagasSchedulingTestHelper:AdvanceTimeAndGetDue(),VerifyCronNextExecution()
- Improved Assertions (Issue #170) - Fluent assertions with chaining
AndConstraint<T>for chained assertionsShouldBeSuccess().And.ShouldSatisfy(x => ...)- Streaming assertions for
IAsyncEnumerable<Either<EncinaError, T>> - Error collection assertions
- TUnit Support (Issue #171) - Source-generated testing framework
EncinaTUnitFixtureadapted for TUnit model- NativeAOT compatible (aligns with Source Generators #50)
- 10-200x faster test execution
- New package planned:
Encina.Testing.TUnit
- Mutation Testing Integration (Issue #172) - Stryker.NET configuration
- Pre-configured
stryker-config.jsonfor Encina projects .github/scripts/run-stryker.cshelper script- GitHub Actions workflow for mutation testing
MutationKillerAttributefor edge case tests
- Pre-configured
- CI/CD Workflow Templates (Issue #173) - Reusable GitHub Actions
encina-test.yml- Basic unit + integration testsencina-matrix.yml- Cross-platform, multi-database testingencina-full-ci.yml- Complete CI with architecture + mutation tests
-
New Labels Created (Testing):
area-testing- Testing utilities and frameworkstesting-integration- Integration testing utilitiestesting-unit- Unit testing utilitiestesting-mocking- Mocking and stubbing utilitiestesting-snapshot- Snapshot and approval testingtesting-data-generation- Test data generation and fixturesarea-mutation-testing- Mutation testing and test qualityarea-architecture-testing- Architecture rules and verificationarea-ci-cd- CI/CD pipelines and automationarea-docker- Docker and containerizationaot-compatible- NativeAOT and trimming compatible
Advanced Distributed Lock Patterns Issues (20 new features planned based on December 2025 research)
-
PostgreSQL Provider (Issue #207) - Native PostgreSQL advisory locks
pg_advisory_lock(key)for exclusive lockspg_advisory_lock_shared(key)for shared lockspg_try_advisory_lock()for non-blocking acquisition- Session-level and transaction-level lock APIs
- No additional table required, uses PostgreSQL native locks
- Inspired by DistributedLock (madelson) - most requested database provider
- MySQL Provider (Issue #208) - GET_LOCK-based locking
GET_LOCK(name, timeout)/RELEASE_LOCK(name)functions- Session-scoped locks with timeout support
- Lock name validation and sanitization
- Compatible with MySQL 5.7+, MariaDB 10.0+
- Azure Blob Storage Provider (Issue #209) - Cloud-native blob leases
- Blob lease acquisition with 15-60s duration (max 60s)
- Auto-renewal background thread
IAzureBlobLockProviderspecialized interface- Health checks for lease monitoring
- Inspired by Azure SDK, Medallion.Threading
- DynamoDB Provider (Issue #210) - AWS-native conditional writes
- Conditional writes with
attribute_not_existsfor lock acquisition - TTL-based automatic expiration
- Heartbeat mechanism for lease extension
- Fence tokens for consistency
- Inspired by AWS DynamoDB Locking Client
- Conditional writes with
- Consul Provider (Issue #211) - HashiCorp session-based locks
- Session-based locking with configurable TTL
- Health check integration for automatic lock release
- Leader election primitives
- Watch for lock state changes
- Inspired by HashiCorp Consul
- etcd Provider (Issue #212) - Lease-based distributed coordination
- etcd lease creation with TTL
- Transaction-based lock acquisition
- Watch for key changes
- Integration with etcd v3 API
- Inspired by etcd.io distributed lock recipe
- ZooKeeper Provider (Issue #213) - Ephemeral sequential nodes
- Ephemeral sequential node creation
- Watch mechanism for predecessor node deletion
- Automatic lock release on session disconnect
- Lock fairness through sequence ordering
- Inspired by Apache ZooKeeper recipes
- Oracle Provider (Issue #214) - DBMS_LOCK package
DBMS_LOCK.REQUEST()/DBMS_LOCK.RELEASE()procedures- Multiple lock modes (Shared, Exclusive)
- Lock handle allocation and management
- Compatible with Oracle 12c+
- Inspired by DistributedLock (madelson)
- Distributed Semaphores (Issue #215) - Counting locks for N-concurrent access
IDistributedSemaphoreinterface with count-based acquisitionTryAcquireAsync(resource, maxCount, expiry)methodGetAvailableCountAsync(resource)for monitoring- Use cases: rate limiting, connection pooling, resource throttling
- Implementations: Redis (Lua scripts), PostgreSQL, SQL Server
- Inspired by DistributedLock (madelson) semaphore support
- Leader Election (Issue #216) - Cluster-wide leader selection
ILeaderElectionProviderinterface for leader managementAcquireLeadershipAsync(),IsLeaderAsync()methodsWatchLeadershipAsync()for change notifications viaIAsyncEnumerable- Automatic lease renewal
- Use cases: singleton services, scheduled job coordination
- Inspired by Consul, etcd, Kubernetes leader election
- Read/Write Locks (Issue #217) - Multiple readers, exclusive writer
IDistributedReadWriteLockProviderinterface- Shared read locks (multiple concurrent readers)
- Exclusive write locks (single writer, no readers)
- Upgrade/downgrade support where possible
- Inspired by PostgreSQL
pg_advisory_lock_shared, ReaderWriterLockSlim
- Fencing Tokens (Issue #218) - Split-brain prevention
- Monotonically increasing token with each lock acquisition
- Storage rejects operations with stale tokens
- Prevents processing with expired locks
- Inspired by Martin Kleppmann "Designing Data-Intensive Applications"
- Multi-Resource Locks (Issue #219) - Atomic multi-lock acquisition
- Acquire multiple resources atomically
- Deadlock prevention via consistent ordering
- All-or-nothing semantics
- Inspired by Two-Phase Locking protocol
- DistributedLockPipelineBehavior (Issue #220) - Declarative handler locking
[DistributedLock("{request.EntityId}", ExpirySeconds = 30)]attribute- Key template support with property placeholders
- Configurable expiry, retry, and wait timeouts
- Automatic lock acquisition/release around handler
- Integration with existing pipeline infrastructure
- LeaderElectionPipelineBehavior (Issue #221) - Leader-only handler execution
[RequiresLeadership("scheduler-leader")]attribute- Handler only executes on current leader node
- Non-leaders receive predefined fallback response
- Automatic leadership monitoring
- Use cases: singleton scheduled jobs, exclusive processors
- OpenTelemetry Integration for Locks (Issue #222) - Metrics and traces
- Metrics:
encina.lock.acquired,encina.lock.released,encina.lock.wait_time,encina.lock.contention - Traces: Spans for lock acquisition, hold duration, release
- Tags: lock type, resource name, outcome (acquired/timeout/failed)
- Integration with existing Encina.OpenTelemetry infrastructure
- Metrics:
- Auto-extend Locks (Issue #223) - Automatic lease extension
- Background renewal for long-running operations
- Configurable extension interval (e.g., renew at 50% of expiry)
- Graceful handling of extension failures
- Prevents accidental lock expiration during processing
- Lock Metadata (Issue #224) - Lock holder information
GetLockInfoAsync(resource)returning holder identity, acquisition time- Useful for debugging and operations
- Optional: machine name, process ID, correlation ID
- Read-only, does not affect lock semantics
- Lock Queuing & Fairness (Issue #225) - FIFO ordering for waiters
- Fair ordering: first waiter acquires lock first
- Prevents starvation of long-waiting requesters
- Optional: priority-based queuing
- Implementations vary by backend capabilities
- RedLock Algorithm (Issue #226) - High-availability multi-Redis locking
- Consensus across N/2+1 Redis instances for lock acquisition
- Clock drift compensation
- Automatic retry with jitter on partial acquisition
IRedLockProvideras wrapper aroundIDistributedLockProvider- Inspired by Redis RedLock specification, RedLock.net
-
New Labels Created (Distributed Lock - December 2025):
area-distributed-lock- Distributed locking patternsarea-leader-election- Leader election and coordinationarea-semaphore- Distributed semaphores and counting locksarea-coordination- Distributed coordination primitivesarea-pipeline- Pipeline behaviors and middleware
Message Transport Patterns Issues (29 new features planned based on December 2025 research)
-
New Message Transports (6 issues):
- Google Cloud Pub/Sub Transport (Issue #237) - Native GCP integration
IMessageTransportPubSubinterface with dead-lettering and ordering keys- Exactly-once delivery (Preview feature), flow control
- Schema validation, message filtering, BigQuery subscriptions
- New package planned:
Encina.Transport.GooglePubSub
- AWS EventBridge Transport (Issue #238) - Event-driven AWS integration
- Event bus publishing with partner/custom buses
- Content-based filtering with event patterns
- Archive and replay, cross-account delivery
- Schema discovery integration
- New package planned:
Encina.Transport.EventBridge
- Apache Pulsar Transport (Issue #239) - Multi-tenant messaging
- Exclusive, Shared, Failover, Key_Shared subscription types
- Topic compaction, tiered storage, geo-replication
- Schema registry with Avro/Protobuf/JSON
- Pulsar Functions integration for stream processing
- New package planned:
Encina.Transport.Pulsar
- Redis Streams Transport (Issue #240) - Redis-native streaming
XADD/XREAD/XREADGROUPcommand integration- Consumer groups with automatic rebalancing
- Stream trimming (
MAXLEN,MINID) - Pending Entry List (PEL) management, message acknowledgment
- New package planned:
Encina.Transport.RedisStreams
- Apache ActiveMQ Artemis Transport (Issue #241) - Enterprise JMS-compatible broker
- AMQP 1.0 and CORE protocol support
- Scheduled messages, last-value queues, ring queues
- Message grouping, large message support
- Divert and bridge configurations
- New package planned:
Encina.Transport.ActiveMQ
- Dapr Transport (Issue #242) - Cloud-agnostic pub/sub abstraction
- Component-based pub/sub (40+ broker implementations)
- CloudEvents format native support
- Bulk publish, per-message metadata
- Subscriber routing rules
- New package planned:
Encina.Transport.Dapr
- Enterprise Integration Patterns (9 issues):
- Message Translator (Issue #243) - Transform message formats between systems
IMessageTranslator<TFrom, TTo>interface- Bidirectional translation support
- AutoMapper and Mapster integration
- Content Enricher (Issue #244) - Augment messages with external data
IContentEnricher<TMessage>interface- Async enrichment from external services
- Caching support for enrichment data
- Splitter Pattern (Issue #245) - Break composite messages into parts
IMessageSplitter<TComposite, TPart>interface- Correlation ID propagation
- Sequential and parallel splitting
- Aggregator Pattern (Issue #246) - Combine related messages
IMessageAggregator<TPart, TResult>interface- Time-based and count-based completion conditions
- Correlation strategies (CorrelationId, custom keys)
- Claim Check Pattern (Issue #247) - Large message handling
IClaimCheckStoreinterface for payload storage- Azure Blob, S3, local filesystem providers
- Automatic check-in/check-out with message metadata
- Async Request-Reply (Issue #248) - Correlation-based responses
IAsyncRequestReply<TRequest, TResponse>interface- Reply-to queue management
- Timeout handling with continuation tokens
- Competing Consumers (Issue #249) - Parallel message processing
ICompetingConsumerPoolinterface- Dynamic scaling based on queue depth
- Affinity and stickiness options
- Message Filter (Issue #250) - Route messages by content
IMessageFilter<TMessage>interface- Predicate-based filtering
- Dead-letter routing for filtered messages
- Priority Queue (Issue #251) - Priority-based message delivery
IMessagePriorityinterface for priority assignment- Multiple priority levels configuration
- Fair scheduling to prevent starvation
- Message Translator (Issue #243) - Transform message formats between systems
- Advanced Transport Features (8 issues):
- Message Batching (Issue #252) - Efficient bulk operations
BatchPublisher<TMessage>with configurable batch size/timeout- Async flush with backpressure
- Per-transport batch optimization
- Native Delayed Delivery (Issue #253) - Broker-native scheduling
IDelayedDeliveryTransportinterfaceDelayUntil(DateTimeOffset),DelayFor(TimeSpan)methods- Fallback to Encina.Scheduling when not supported
- Message Deduplication (Issue #254) - Transport-level idempotency
IDeduplicationStrategyinterface- Content-hash, Message-ID, custom key strategies
- Configurable deduplication window
- Partitioning (Issue #255) - Ordered message delivery
IPartitionKeyProvider<TMessage>interface- Consistent hashing for partition assignment
- Partition affinity for stateful consumers
- Consumer Groups (Issue #256) - Coordinated consumption
IConsumerGroupinterface- Automatic partition assignment and rebalancing
- Offset tracking and commit strategies
- Bidirectional Streaming (Issue #257) - gRPC streaming support
IStreamingTransport<TRequest, TResponse>interface- Client and server streaming modes
- Flow control and backpressure
- Message Compression (Issue #258) - Payload compression
IMessageCompressorinterface- Gzip, Brotli, LZ4, Snappy algorithms
- Content-encoding negotiation
- Schema Registry Integration (Issue #259) - Schema evolution
ISchemaRegistryinterface- Confluent Schema Registry, AWS Glue support
- Compatibility checks (BACKWARD, FORWARD, FULL)
- Message Batching (Issue #252) - Efficient bulk operations
- Transport Interoperability (3 issues):
- CloudEvents Format Support (Issue #260) - CNCF standard events
ICloudEventsSerializerinterface- Structured and binary content modes
- Extension attributes support
- NServiceBus Interoperability (Issue #261) - Bridge to NServiceBus
- Message format translation
- Header mapping (NServiceBus ↔ Encina)
- Gateway pattern for gradual migration
- MassTransit Interoperability (Issue #262) - Bridge to MassTransit
- Envelope format translation
- Consumer adapter patterns
- Saga state migration utilities
- CloudEvents Format Support (Issue #260) - CNCF standard events
- Transport Observability (3 issues):
- Transport Health Checks (Issue #263) - Liveness and readiness probes
ITransportHealthCheckinterface per transport- Connection state, queue depth, consumer lag
- ASP.NET Core Health Checks integration
- Transport Metrics (Issue #264) - Performance metrics
- Messages sent/received/failed per transport
- Latency histograms (P50, P95, P99)
- OpenTelemetry Metrics integration
- Transport Distributed Tracing (Issue #265) - End-to-end tracing
- W3C Trace Context propagation
- Span creation for publish/consume operations
- Baggage propagation for cross-service context
- Transport Health Checks (Issue #263) - Liveness and readiness probes
- Google Cloud Pub/Sub Transport (Issue #237) - Native GCP integration
-
New Labels Created (Message Transport - December 2025):
transport-rabbitmq- RabbitMQ transport providertransport-kafka- Apache Kafka transport providertransport-azure-sb- Azure Service Bus transport providertransport-sqs- AWS SQS transport providertransport-redis- Redis transport providertransport-nats- NATS transport providertransport-pulsar- Apache Pulsar transport providertransport-grpc- gRPC transport providertransport-dapr- Dapr transport providertransport-eventbridge- AWS EventBridge transport providertransport-pubsub- Google Cloud Pub/Sub transport providertransport-activemq- Apache ActiveMQ Artemis transport provider
-
New Labels Created (Previously):
area-scheduling- Scheduling and recurring message patternsarea-saga- Saga and Process Manager patternsarea-encryption- Message encryption and data protectionarea-scalability- Horizontal scaling and consumer patternsarea-polly- Polly v8 integration and resilience strategiesnetflix-pattern- Patterns inspired by Netflix OSSindustry-best-practice- Industry-proven patterns from major tech companiesmeta-pattern- Patterns inspired by Meta/Facebook infrastructure (FOQS, etc.)
-
CLI Scaffolding Tool (
Encina.Cli) - Issue #47:encina new <template> <name>- Create new Encina projects (api, worker, console)- Options:
--database,--caching,--transport,--output,--force
- Options:
encina generate handler <name>- Generate command handlers with optional response typesencina generate query <name> --response <type>- Generate query handlersencina generate saga <name> --steps <steps>- Generate saga definitionsencina generate notification <name>- Generate notifications and handlersencina add caching|database|transport|validation|resilience|observability- Add packages- Built with System.CommandLine 2.0 and Spectre.Console
- Packaged as .NET global tool (
dotnet tool install Encina.Cli) - Comprehensive test coverage: 65 tests (unit, guard)
Clean Architecture Patterns Issues (2 new features planned based on December 29, 2025 research)
-
Result Pattern Extensions (Issue #468) - Fluent API for Either
EitherCombineExtensions:Combine<T1, T2>(),Combine<T1, T2, T3>()for combining multiple resultsEitherAccumulateExtensions: Error accumulation instead of fail-fastEitherAsyncExtensions:BindAsync(),MapAsync(),TapAsync()for async chainsEitherHttpExtensions:ToProblemDetails(),ToActionResult(),ToResult()for Minimal APIsEitherConditionalExtensions:When(),Ensure(),OrElse()for conditional operations- Inspired by FluentResults, language-ext, CSharpFunctionalExtensions
- Priority: MEDIUM - Improves ROP ergonomics
- Partitioned Sequential Messaging (Issue #469) - Wolverine 5.0-inspired pattern
IPartitionedMessageinterface withPartitionKey- Specialized interfaces:
ISagaPartitionedMessage,ITenantPartitionedMessage,IAggregatePartitionedMessage IPartitionedQueueManagerwith System.Threading.ChannelsPartitionedMessageBehaviorfor pipeline integrationIPartitionStorefor optional durability- Messages with same PartitionKey process sequentially; different partitions in parallel
- Priority: MEDIUM - Critical for saga workflows and multi-tenancy
-
New labels created for Clean Architecture Patterns:
area-value-objects- Value Objects and domain primitives (#2E8B57)area-strongly-typed-ids- Strongly Typed IDs and identity patterns (#2E8B57)area-specification-pattern- Specification pattern for queries (#2E8B57)area-domain-services- Domain Services abstraction (#2E8B57)area-result-pattern- Result/Either pattern and functional error handling (#9932CC)area-bounded-context- Bounded Context and module boundaries (#2E8B57)
Removed
- API Versioning Helpers (Issue #54) - Closed as "won't fix".
Asp.Versioningprovides complete HTTP-level versioning; adding[ApiVersion]to CQRS handlers would be redundant since versioning belongs on the public API surface (controllers/endpoints), not internal handlers.
Deferred
- ODBC Provider (Issue #56) - Moved to post-1.0 evaluation. Valuable for legacy database scenarios but not critical for core 1.0 release.
Added (Patterns & Infrastructure)
-
Scatter-Gather Pattern (Issue #63):
- Enterprise Integration Pattern for sending requests to multiple handlers and aggregating results
IScatterGatherRunnerinterface withExecuteAsyncmethod returningEither<EncinaError, ScatterGatherResult<T>>ScatterGatherBuilderfluent API for defining scatter-gather operations:ScatterTo(name, handler)for adding scatter handlers with multiple overloads (sync/async, with/without Either)WithPriority(int)for handler ordering (lower = higher priority)WithMetadata(key, value)for handler metadataExecuteInParallel(maxDegreeOfParallelism?)/ExecuteSequentially()for execution modeWithTimeout(TimeSpan)for operation timeout
- Four gather strategies via
GatherStrategyenum:WaitForAll- Wait for all handlers to complete (fail on any failure)WaitForFirst- Return on first successful responseWaitForQuorum- Return when quorum count is reachedWaitForAllAllowPartial- Wait for all, tolerate partial failures
- Gather configuration via
GatherBuilder:GatherAll()/GatherFirst()/GatherQuorum(count)/GatherAllAllowingPartialFailures()GatherWith(GatherStrategy, quorumCount?)for explicit strategy- Aggregation methods:
TakeFirst(),TakeMin(),TakeMax(),Aggregate(),AggregateSuccessful()
ScatterGatherResult<TResponse>with execution metrics:Response- Aggregated resultScatterResults- List ofScatterExecutionResult<TResponse>with handler name, result, durationSuccessCount,FailureCount,OperationId,TotalDuration
ScatterGatherOptionsconfiguration:DefaultTimeout(default: 30s)ExecuteScattersInParallel(default: true)MaxDegreeOfParallelism(default: null/unlimited)
ScatterGatherErrorCodesfor standardized error codes:scattergather.cancelled,scattergather.timed_outscattergather.all_scatters_failed,scattergather.quorum_not_reachedscattergather.gather_failed,scattergather.scatter_failed
- High-performance logging with
LoggerMessagesource generators (EventIds 600-615) - DI integration via
MessagingConfiguration.UseScatterGather = true - Comprehensive test coverage: 131 tests (unit, property, contract, guard, load)
- Benchmarks for scatter-gather performance across strategies
- Example: a fully working, copy-pastable scatter-gather example is available in the documentation. The changelog previously contained simplified placeholder snippets; the full examples (with imports and helper implementations) live in the documentation to avoid non-compilable copy/paste.
-
Content-Based Router (Issue #64):
-
Enterprise Integration Pattern for routing messages based on content inspection
-
IContentRouterinterface withRouteAsyncmethods returningEither<EncinaError, ContentRouterResult<T>> -
ContentRouterBuilderfluent API for defining routing rules:When(condition)/When(name, condition)for conditional routesRouteTo(handler)with multiple overloads (sync/async, with/without Either)WithPriority(int)for route ordering (lower = higher priority)WithMetadata(key, value)for route metadataDefault(handler)/DefaultResult(value)for fallback handlingBuild()to create immutableBuiltContentRouterDefinition<TMessage, TResult>
-
ContentRouterOptionsconfiguration:ThrowOnNoMatch- Return error when no route matches (default: true)AllowMultipleMatches- Execute all matching routes (default: false)EvaluateInParallel- Parallel route execution withMaxDegreeOfParallelism
-
ContentRouterResult<TResult>with execution metrics:RouteResults- List ofRouteExecutionResult<TResult>with route name, result, durationMatchedRouteCount,TotalDuration,UsedDefaultRoute
-
RouteDefinition<TMessage, TResult>for route configuration -
ContentRouterErrorCodesfor standardized error codes:contentrouter.no_matching_route,contentrouter.route_execution_failedcontentrouter.cancelled,contentrouter.invalid_configuration
-
High-performance logging with
LoggerMessagesource generators -
DI integration via
MessagingConfiguration.UseContentRouter = true -
Comprehensive test coverage: 117 tests (unit, integration, property, contract, guard, load)
-
Benchmarks for routing performance
-
Example:
// RouteTo accepts both sync and async handlers var definition = ContentRouterBuilder.Create<Order, string>() .When("HighValue", o => o.Total > 10000) .WithPriority(1) .RouteTo(async (o, ct) => await ProcessHighValueOrder(o, ct)) .When("International", o => o.IsInternational) .WithPriority(2) .RouteTo(async (o, ct) => await Task.FromResult(Right<EncinaError, string>("InternationalHandler"))) .Default(async (o, ct) => await Task.FromResult(Right<EncinaError, string>("StandardHandler"))) .Build(); var result = await router.RouteAsync(definition, order);
-
-
Distributed Lock Abstractions (Issue #55):
- Encina.DistributedLock - Core abstractions for distributed locking
IDistributedLockProviderinterface withTryAcquireAsync,AcquireAsync,IsLockedAsync,ExtendAsyncILockHandleinterface with lock metadata (Resource,LockId,AcquiredAtUtc,ExpiresAtUtc,IsReleased)LockAcquisitionExceptionfor lock acquisition failuresDistributedLockOptionswithKeyPrefix,DefaultExpiry,DefaultWait,DefaultRetry,ProviderHealthCheck- DI registration via
AddEncinaDistributedLock()
- Encina.DistributedLock.InMemory - In-memory provider for testing
InMemoryDistributedLockProviderwithConcurrentDictionarystorageInMemoryLockOptionswithWarnOnUseflagTimeProviderinjection for testability- DI registration via
AddEncinaDistributedLockInMemory()
- Encina.DistributedLock.Redis - Redis provider for production
RedisDistributedLockProviderusing StackExchange.Redis- Lua scripts for atomic lock release (owner verification)
- Wire-compatible with Redis, Garnet, Valkey, Dragonfly, KeyDB
RedisLockOptionswithDatabaseandKeyPrefixRedisDistributedLockHealthCheckimplementingIEncinaHealthCheck- DI registration via
AddEncinaDistributedLockRedis()
- Encina.DistributedLock.SqlServer - SQL Server provider
SqlServerDistributedLockProviderusingsp_getapplock/sp_releaseapplock- Session-scoped locks with automatic release on connection close
SqlServerLockOptionswithConnectionStringandKeyPrefixSqlServerDistributedLockHealthCheckimplementingIEncinaHealthCheck- DI registration via
AddEncinaDistributedLockSqlServer()
- Updated
Encina.Cachingto referenceEncina.DistributedLockabstractions - Comprehensive test coverage:
- Unit tests for all providers
- Integration tests with Testcontainers (Redis, SQL Server)
- Property-based tests with FsCheck
- Contract tests for
IDistributedLockProvider - Guard clause tests for all public APIs
- Load tests for high concurrency scenarios
- Benchmarks for performance validation
- Full documentation with usage examples
- Encina.DistributedLock - Core abstractions for distributed locking
-
Module-scoped Pipeline Behaviors (Issue #58):
- IModulePipelineBehavior<TModule, TRequest, TResponse> interface for module-specific behaviors
- ModuleBehaviorAdapter wraps module behaviors and filters execution by module ownership
- IModuleHandlerRegistry maps handler types to their owning modules via assembly association
- Request context extensions for module information:
GetModuleName()for retrieving current module nameWithModuleName()for setting module name (overloads for string and IModule)IsInModule()for checking if context is in a specific module
- DI extension methods:
AddEncinaModuleBehavior<TModule, TRequest, TResponse, TBehavior>()for registration- Overload with
ServiceLifetimeparameter for custom lifetimes
- Case-insensitive module name matching
- Null Object pattern with
NullModuleHandlerRegistryfor when modules aren't configured - Comprehensive test coverage: 100 module-related unit tests
-
AWS Lambda Integration (Issue #60):
- Encina.AwsLambda package for serverless function execution on AWS
- API Gateway integration with result-to-response extensions:
ToApiGatewayResponse<T>()for standard 200 OK responsesToCreatedResponse<T>()for 201 Created with Location headerToNoContentResponse()for 204 No Content responsesToHttpApiResponse<T>()for HTTP API (V2) responses
ToProblemDetailsResponse()for RFC 7807 compliant error responses- SQS trigger support with batch processing:
ProcessBatchAsync<T>()for partial batch failure reporting viaSQSBatchResponseProcessAllAsync()for all-or-nothing processingDeserializeMessage<T>()for type-safe message deserialization- Automatic
BatchItemFailuresfor failed message IDs
- EventBridge (CloudWatch Events) integration:
ProcessAsync<TDetail, TResult>()for strongly-typed event handlingProcessRawAsync<TDetail, TResult>()for raw JSON event processingGetMetadata()for extracting event metadataEventBridgeMetadataclass with Id, Source, DetailType, Account, Region, Time
LambdaContextExtensionsfor context information access:GetCorrelationId(),GetUserId(),GetTenantId()GetAwsRequestId(),GetFunctionName(),GetRemainingTimeMs()
EncinaAwsLambdaOptionsfor configuration:EnableRequestContextEnrichmenttoggle- Customizable header names (
CorrelationIdHeader,TenantIdHeader) - Claim types (
UserIdClaimType,TenantIdClaimType) IncludeExceptionDetailsInResponsefor development debuggingUseApiGatewayV2Format,EnableSqsBatchItemFailurestogglesProviderHealthCheckconfiguration
AwsLambdaHealthCheckimplementingIEncinaHealthCheck- Error code to HTTP status mapping:
validation.*→ 400 Bad Requestauthorization.unauthenticated→ 401 Unauthorizedauthorization.*→ 403 Forbidden*.not_found,*.missing→ 404 Not Found*.conflict,*.already_exists,*.duplicate→ 409 Conflict
- DI registration via
AddEncinaAwsLambda() - Comprehensive test coverage: 97 unit, 21 contract, 10 property, 21 guard tests
- Benchmarks for API Gateway response creation performance
- Full documentation with examples for API Gateway, SQS, and EventBridge triggers
-
Azure Functions Integration (Issue #59):
- Encina.AzureFunctions package for serverless function execution
- HTTP Trigger integration with automatic result-to-response conversion:
ToHttpResponseData<T>()for standard responsesToCreatedResponse<T>()for 201 Created with Location headerToNoContentResponse()for 204 No Content responses
ToProblemDetailsResponse()for RFC 7807 compliant error responsesEncinaFunctionMiddlewarefor request context enrichment:- Automatic correlation ID extraction/generation
- User ID extraction from claims
- Tenant ID extraction from headers or claims
- Structured logging for function execution
FunctionContextExtensionsfor context information access:GetCorrelationId(),GetUserId(),GetTenantId(),GetInvocationId()
EncinaAzureFunctionsOptionsfor configuration:EnableRequestContextEnrichmenttoggle- Customizable header names and claim types
IncludeExceptionDetailsInResponsefor developmentProviderHealthCheckconfiguration
AzureFunctionsHealthCheckimplementingIEncinaHealthCheck- Error code to HTTP status mapping:
validation.*→ 400 Bad Requestauthorization.unauthenticated→ 401 Unauthorizedauthorization.*→ 403 Forbidden*.not_found,*.missing→ 404 Not Found*.conflict,*.already_exists,*.duplicate→ 409 Conflict
- DI registration via
AddEncinaAzureFunctions() - Middleware registration via
builder.UseEncinaMiddleware() - Comprehensive test coverage: unit, contract, property, guard, benchmarks
- Full documentation with examples for HTTP, Queue, and Timer triggers
-
Durable Functions Integration (Issue #61):
- Azure Durable Functions support with Railway Oriented Programming (ROP)
OrchestrationContextExtensionsfor ROP-compatible activity calls:CallEncinaActivityAsync<TInput, TResult>()for Either-returning activitiesCallEncinaActivityWithResultAsync<TInput, TResult>()for ActivityResult activitiesCallEncinaSubOrchestratorAsync<TInput, TResult>()for sub-orchestratorsWaitForEncinaExternalEventAsync<T>()for external events with timeoutCreateRetryOptions()for retry configurationGetCorrelationId()for instance ID access
ActivityResult<T>serializable wrapper for Either results:Success()andFailure()factory methodsToEither()for conversion back to EitherToActivityResult()extension for Either conversion
DurableSagaBuilderfluent API for saga workflows:Step()for adding saga stepsExecute()andCompensate()for activity configurationWithRetry()for step-level retry optionsSkipCompensationOnFailure()for idempotent operationsWithTimeout()for saga-level timeoutWithDefaultRetryOptions()for default retry configuration- Automatic compensation in reverse order on failure
DurableSaga<TData>executable saga withExecuteAsync()DurableSagaErrorwith original error and compensation results- Fan-out/fan-in pattern extensions:
FanOutAsync<TInput, TResult>()for parallel activity executionFanOutAllAsync<TInput, TResult>()requiring all to succeedFanOutFirstSuccessAsync<TInput, TResult>()returning first successFanOutMultipleAsync<T1, T2>()for different activities in parallelPartition<T>()for separating successes from failures
DurableFunctionsOptionsfor configuration:DefaultMaxRetries,DefaultFirstRetryInterval,DefaultBackoffCoefficientDefaultMaxRetryInterval,ContinueCompensationOnError,DefaultSagaTimeoutProviderHealthCheckconfiguration
DurableFunctionsHealthCheckimplementingIEncinaHealthCheck- DI registration via
AddEncinaDurableFunctions() - Comprehensive test coverage: 124 unit, 58 contract, 27 property, 19 guard tests
- Full documentation with examples for orchestrations, sagas, and fan-out/fan-in
-
Routing Slip Pattern for Dynamic Message Routing (Issue #62):
-
RoutingSlipBuilderfluent API for defining routing slips with inline step definitions -
RoutingSlipStepBuilderfor configuring individual steps with execute and compensate functions -
BuiltRoutingSlipDefinition<TData>immutable definition ready for execution -
RoutingSlipStepDefinition<TData>representing a single step in the itinerary -
RoutingSlipContext<TData>for dynamic route modification during execution:AddStep(),AddStepNext(),InsertStep()for adding stepsRemoveStepAt(),ClearRemainingSteps()for removing stepsGetRemainingStepNames()for inspecting itinerary
-
RoutingSlipActivityEntry<TData>for activity log with compensation data -
RoutingSlipResult<TData>with execution metrics:RoutingSlipId,FinalData,StepsExecuted,StepsAdded,StepsRemovedDuration,ActivityLog
-
IRoutingSlipRunnerinterface andRoutingSlipRunnerimplementation with:- Step-by-step execution with dynamic modification tracking
- Automatic compensation in reverse order on failure
- Configurable compensation failure handling
- High-performance logging with LoggerMessage (EventIds 400-415)
-
RoutingSlipOptionsfor configuration:DefaultTimeout,StuckCheckInterval,StuckThreshold,BatchSizeContinueCompensationOnFailure(default: true)
-
RoutingSlipStatusconstants: Running, Completed, Compensating, Compensated, Failed, TimedOut -
RoutingSlipErrorCodeswith error codes:routingslip.not_found,routingslip.invalid_status,routingslip.step_failedroutingslip.compensation_failed,routingslip.timeoutroutingslip.handler.cancelled,routingslip.handler.failed
-
DI integration via
MessagingConfiguration.UseRoutingSlips -
Comprehensive test coverage: 137+ tests (unit, property, guard)
-
Example:
var definition = RoutingSlipBuilder.Create<OrderData>("ProcessOrder") .Step("Validate Order") .Execute(async (data, ctx, ct) => { // Validation logic return Right<EncinaError, OrderData>(data); }) .Step("Process Payment") .Execute(async (data, ctx, ct) => { // Dynamically add verification step if needed if (data.RequiresVerification) ctx.AddStepNext(verificationStep); return Right<EncinaError, OrderData>(data); }) .Compensate(async (data, ctx, ct) => await RefundPaymentAsync(data)) .Step("Ship Order") .Execute(async (data, ctx, ct) => { data.TrackingNumber = await ShipAsync(data); return Right<EncinaError, OrderData>(data); }) .Compensate(async (data, ctx, ct) => await CancelShipmentAsync(data)) .OnCompletion(async (data, ctx, ct) => await NotifyCompletedAsync(data)) .WithTimeout(TimeSpan.FromMinutes(5)) .Build(); var result = await runner.RunAsync(definition, new OrderData());
-
-
Event Versioning/Upcasting for Schema Evolution (Issue #37):
-
IEventUpcastermarker interface for event upcasters withSourceEventTypeName,TargetEventType,SourceEventType -
IEventUpcaster<TFrom, TTo>strongly-typed generic interface withUpcast(TFrom)method -
EventUpcasterBase<TFrom, TTo>abstract base class wrapping Marten'sEventUpcaster<TFrom, TTo> -
LambdaEventUpcaster<TFrom, TTo>for inline lambda-based upcasting without dedicated classes -
EventUpcasterRegistryfor discovering and managing event upcasters:Register<TUpcaster>(),Register(Type),Register(IEventUpcaster)registration methodsTryRegister()for non-throwing duplicate handlingGetUpcasterForEventType(string),GetAllUpcasters(),HasUpcasterFor(string)lookup methodsScanAndRegister(Assembly)for automatic assembly scanning
-
EventVersioningOptionsfor configuration:Enabledtoggle (default: false)ThrowOnUpcastFailureoption (default: true)AddUpcaster<TUpcaster>()for type registrationAddUpcaster<TFrom, TTo>(Func<TFrom, TTo>)for inline lambda registrationScanAssembly(Assembly),ScanAssemblies(params Assembly[])for assembly scanningApplyTo(EventUpcasterRegistry)for applying configuration to registry
-
ConfigureMartenEventVersioningasIConfigureOptions<StoreOptions>for Marten integration -
EventVersioningErrorCodeswith error codes:event.versioning.upcast_failed,event.versioning.upcaster_not_foundevent.versioning.registration_failed,event.versioning.duplicate_upcasterevent.versioning.invalid_configuration
-
VersioningLoghigh-performance logging with LoggerMessage source generators (EventIds 100-129) -
DI integration via
AddEventVersioning()internal method -
AddEventUpcaster<TUpcaster>()extension method for individual upcaster registration -
Comprehensive test coverage: 85+ tests (unit, property, contract, guard, integration)
-
Example:
// Define upcaster class public class OrderCreatedV1ToV2Upcaster : EventUpcasterBase<OrderCreatedV1, OrderCreatedV2> { protected override OrderCreatedV2 Upcast(OrderCreatedV1 old) => new(old.OrderId, old.CustomerName, Email: "unknown@example.com"); } // Configure with class-based upcasters services.AddEncinaMarten(options => { options.EventVersioning.Enabled = true; options.EventVersioning.AddUpcaster<OrderCreatedV1ToV2Upcaster>(); options.EventVersioning.ScanAssembly(typeof(Program).Assembly); }); // Or use inline lambda for simple transformations services.AddEncinaMarten(options => { options.EventVersioning.Enabled = true; options.EventVersioning.AddUpcaster<OrderCreatedV1, OrderCreatedV2>( old => new OrderCreatedV2(old.OrderId, old.CustomerName, "migrated@example.com")); });
-
-
Snapshotting for large aggregates (Issue #52):
-
ISnapshotable<TAggregate>marker interface for aggregates supporting snapshots -
ISnapshot<TAggregate>interface withAggregateId,Version,CreatedAtUtcproperties -
Snapshot<TAggregate>sealed class storing aggregate state at a specific version -
SnapshotOptionsfor global and per-aggregate configuration:Enabled- toggle snapshotting (default: false)SnapshotEvery- event threshold for snapshot creation (default: 100)KeepSnapshots- retention limit (default: 3, 0 = keep all)AsyncSnapshotCreation- async vs sync snapshot creation (default: true)ConfigureAggregate<T>(snapshotEvery, keepSnapshots)for per-aggregate overrides
-
ISnapshotStore<TAggregate>interface for snapshot storage:SaveAsync,GetLatestAsync,PruneAsyncwith ROP error handling
-
MartenSnapshotStore<TAggregate>Marten-based implementation:- PostgreSQL document storage via Marten
- Composite key:
{AggregateType}:{AggregateId}:{Version} - Automatic pruning of old snapshots
-
SnapshotEnvelope<TAggregate>document wrapper for Marten storage -
SnapshotAwareAggregateRepository<TAggregate>for optimized aggregate loading:- Loads from latest snapshot + replays only subsequent events
- Automatic snapshot creation when threshold exceeded
- Falls back to standard event replay if no snapshot exists
-
SnapshotErrorCodeswith standardized error codes:snapshot.load_failed,snapshot.save_failed,snapshot.prune_failed,snapshot.invalid_state
-
High-performance logging with
LoggerMessagesource generators (EventIds 100-159) -
DI registration via
AddSnapshotableAggregate<TAggregate>() -
Comprehensive test coverage: 121 unit tests, property tests, contract tests, guard clause tests
-
Integration tests with Testcontainers/PostgreSQL
-
Example:
// Enable snapshotting for aggregates services.AddEncinaMarten(options => { options.Snapshots.Enabled = true; options.Snapshots.SnapshotEvery = 100; options.Snapshots.KeepSnapshots = 3; // Per-aggregate configuration options.Snapshots.ConfigureAggregate<Order>( snapshotEvery: 50, keepSnapshots: 5); }); // Register snapshotable aggregate services.AddSnapshotableAggregate<Order>(); // Aggregate must implement ISnapshotable<TAggregate> public class Order : AggregateBase, ISnapshotable<Order> { // ... standard aggregate implementation }
-
-
Projections/Read Models for CQRS read side (Issue #36):
-
IReadModelinterface for read model abstraction withGuid Idproperty -
IReadModel<TId>generic variant for strongly-typed identifiers -
IProjection<TReadModel>interface withProjectionNameproperty -
IProjectionHandler<TEvent, TReadModel>for handling events on existing read models:Apply(TEvent, TReadModel, ProjectionContext)method
-
IProjectionCreator<TEvent, TReadModel>for creating read models from events:Create(TEvent, ProjectionContext)method
-
IProjectionDeleter<TEvent, TReadModel>for conditional deletion:ShouldDelete(TEvent, TReadModel, ProjectionContext)method
-
ProjectionContextwith event metadata:StreamId,SequenceNumber,GlobalPosition,TimestampEventType,CorrelationId,CausationId,Metadata
-
IReadModelRepository<TReadModel>for read model persistence:GetByIdAsync,GetByIdsAsync,QueryAsyncStoreAsync,StoreManyAsync,DeleteAsync,DeleteAllAsyncExistsAsync,CountAsync- ROP-based error handling with
Either<EncinaError, T>
-
IProjectionManagerfor projection lifecycle management:RebuildAsync<TReadModel>with configurable optionsGetStatusAsync,GetAllStatusesAsyncfor monitoringStartAsync,StopAsync,PauseAsync,ResumeAsynclifecycle methods
-
RebuildOptionsfor rebuild configuration:BatchSize(default 1000),DeleteExisting,OnProgresscallbackStartPosition,EndPositionfor incremental rebuildsRunInBackgroundfor async rebuilding
-
ProjectionStatuswith state tracking:Stateenum:Stopped,Starting,Running,CatchingUp,Rebuilding,Paused,Faulted,StoppingLastProcessedPosition,EventsProcessed,LastUpdatedAtUtc,ErrorMessage
-
ProjectionRegistryfor projection registration and discovery:Register<TProjection, TReadModel>()methodGetProjectionsForEvent(Type),GetProjectionForReadModel<T>(),GetAllProjections()
-
IInlineProjectionDispatcherfor synchronous projection updates:DispatchAsync(object, ProjectionContext)for single eventDispatchManyAsync(IEnumerable<(object, ProjectionContext)>)for batch
-
Marten implementations:
MartenReadModelRepository<TReadModel>with Marten IDocumentSessionMartenProjectionManagerwith event stream processingMartenInlineProjectionDispatcherfor inline projection updates
-
ProjectionOptionsfor configuration:EnableInlineProjections,RebuildOnStartupDefaultBatchSize,MaxConcurrentRebuildsOnProjectionFaultedcallback
-
IProjectionRegistrarinterface for startup registration -
DI registration via
AddProjection<TProjection, TReadModel>() -
High-performance logging with
LoggerMessageattributes -
80 tests: 30 unit, 22 property-based, 11 contract, 17 guard clause
-
Note: Example uses target-typed
new()andwithexpression (requires read model to be arecordtype). See Language Requirements. -
Context-to-Model Mapping:
ctx.StreamIdis aGuid(non-nullable struct, defaults toGuid.Empty). This maps directly toIReadModel.Idto correlate read models with their source aggregates. Guard againstGuid.Emptyif your domain requires a valid stream ID. -
Null Handling: Event properties (e.g.,
e.CustomerName) may be null depending on your domain model. TheCreatemethod should validate required fields withArgumentNullException.ThrowIfNull()or use null-coalescing for optional fields. The example below demonstrates defensive validation. -
Example:
// Define a read model (must be a record to use 'with' expression) public record OrderSummary : IReadModel { public Guid Id { get; set; } public string CustomerName { get; set; } = string.Empty; public decimal TotalAmount { get; set; } } // Define a projection with input validation public class OrderSummaryProjection : IProjection<OrderSummary>, IProjectionCreator<OrderCreated, OrderSummary>, IProjectionHandler<OrderItemAdded, OrderSummary> { public string ProjectionName => "OrderSummary"; public OrderSummary Create(OrderCreated e, ProjectionContext ctx) { // StreamId is a non-nullable Guid; validate against Guid.Empty only if your domain requires // Guid.Empty typically indicates "no meaningful identifier" - domain logic decides if this is valid if (ctx.StreamId == Guid.Empty) throw new ArgumentException("StreamId must represent a valid aggregate identifier", nameof(ctx)); // Validate required event properties ArgumentNullException.ThrowIfNull(e.CustomerName, nameof(e.CustomerName)); return new() { Id = ctx.StreamId, CustomerName = e.CustomerName }; } public OrderSummary Apply(OrderItemAdded e, OrderSummary m, ProjectionContext ctx) => m with { TotalAmount = m.TotalAmount + e.Price * e.Quantity }; } // Register and use services.AddEncinaMarten(options => { options.Projections.EnableInlineProjections = true; }).AddProjection<OrderSummaryProjection, OrderSummary>(); // Query read models var summary = await repository.GetByIdAsync(orderId);
-
-
Bulkhead Isolation Pattern (Issue #53):
-
BulkheadAttributefor attribute-based bulkhead configuration:MaxConcurrency- Maximum parallel executions allowed (default: 10)MaxQueuedActions- Additional requests that can wait in queue (default: 20)QueueTimeoutMs- Maximum time to wait in queue (default: 30000ms)
-
IBulkheadManagerinterface for bulkhead management:TryAcquireAsync- Acquire permit with timeout and cancellation supportGetMetrics- Get current bulkhead metrics (concurrency, queue, rejection rate)Reset- Reset bulkhead state for a key
-
BulkheadManagerimplementation withSemaphoreSlim:- Thread-safe concurrent dictionary for per-key bulkhead isolation
- Automatic permit release via
IDisposablepattern TimeProviderinjection for testability
-
BulkheadPipelineBehavior<TRequest, TResponse>for automatic bulkhead enforcement -
BulkheadAcquireResultrecord struct with factory methods:Acquired()- Successful acquisition with releaserRejectedBulkheadFull()- Both concurrency and queue limits reachedRejectedQueueTimeout()- Queue wait timeout exceededRejectedCancelled()- Request cancelled while waiting
-
BulkheadMetricsrecord struct with calculated properties:ConcurrencyUtilization- Percentage of concurrency capacity in useQueueUtilization- Percentage of queue capacity in useRejectionRate- Total rejection rate as percentage
-
BulkheadRejectionReasonenum (None,BulkheadFull,QueueTimeout,Cancelled) -
Automatic DI registration via
AddEncinaPolly()(singleton manager) -
Comprehensive test coverage: unit, integration, property-based, contract, guard, load tests
-
Performance benchmarks for acquire/release operations
-
Example:
// Limit payment processing to 10 concurrent executions [Bulkhead(MaxConcurrency = 10, MaxQueuedActions = 20)] public record ProcessPaymentCommand(PaymentData Data) : ICommand<PaymentResult>; // Limit external API calls with custom timeout [Bulkhead(MaxConcurrency = 5, MaxQueuedActions = 10, QueueTimeoutMs = 5000)] public record CallExternalApiQuery(string Endpoint) : IRequest<ApiResponse>;
-
-
Dead Letter Queue (Issue #42):
-
IDeadLetterMessageinterface for dead letter message abstraction -
IDeadLetterStoreinterface for provider-agnostic storage:AddAsync,GetAsync,GetMessagesAsync,GetCountAsyncMarkAsReplayedAsync,DeleteAsync,DeleteExpiredAsync- Pagination support with
skipandtakeparameters
-
IDeadLetterMessageFactoryfor creating messages from failed requests -
DeadLetterFilterfor querying messages:- Factory methods:
All,FromSource,Since,ByCorrelationId - Filter by source pattern, request type, correlation ID, date range
ExcludeReplayedoption for pending messages only
- Factory methods:
-
DeadLetterOptionsfor configuration:RetentionPeriod- how long to keep messages (default: 30 days)CleanupInterval- background cleanup frequency (default: 1 hour)EnableAutomaticCleanup- toggle cleanup processor- Integration flags:
IntegrateWithRecoverability,IntegrateWithOutbox, etc. OnDeadLettercallback for custom notifications
-
DeadLetterOrchestratorfor coordinating DLQ operations -
IDeadLetterManagerwith message replay capabilities:ReplayAsync(messageId)- replay single messageReplayAllAsync(filter)- batch replay with filterGetStatisticsAsync()- queue statisticsCleanupExpiredAsync()- manual cleanup
-
DeadLetterManagerimplementation with reflection-based replay -
ReplayResultandBatchReplayResultfor replay operation results -
DeadLetterStatisticswith counts by source pattern -
DeadLetterHealthCheckwith warning/critical thresholds:- Configurable
WarningThreshold(default: 10 messages) - Configurable
CriticalThreshold(default: 100 messages) OldMessageThresholdfor stale message detection
- Configurable
-
DeadLetterCleanupProcessorbackground service for automatic cleanup -
DeadLetterSourcePatternsconstants: Recoverability, Outbox, Inbox, Scheduling, Saga, Choreography -
DeadLetterErrorCodesfor standardized error codes -
High-performance logging with
LoggerMessageattributes -
DI registration via
AddEncinaDeadLetterQueue<TStore, TFactory>() -
Comprehensive test coverage: 75 unit tests, 11 integration tests, 22 property tests, 12 contract tests
-
Built-in vs Custom Implementations:
- Built-in (Testing):
FakeDeadLetterStoreinEncina.Testing.Fakes- In-memory store for unit/integration tests - Custom (Production): Implement
IDeadLetterStoreandIDeadLetterMessageFactoryfor your persistence layer (EF Core, Dapper, ADO.NET, NoSQL, etc.) - API Location: Interface contracts in
Encina.Messaging.DeadLetternamespace (IDeadLetterStore.cs,IDeadLetterMessageFactory.cs) - Contract Tests: Use
IDeadLetterStoreContractTestsbase class to verify custom implementations - Sample Implementation: See
src/Encina.Testing.Fakes/Stores/FakeDeadLetterStore.csfor implementation reference
- Built-in (Testing):
-
Example (Testing with built-in FakeDeadLetterStore):
// Testing scenario: Use built-in FakeDeadLetterStore services.AddEncinaDeadLetterQueue<FakeDeadLetterStore, FakeDeadLetterMessageFactory>(options => { options.RetentionPeriod = TimeSpan.FromDays(30); options.EnableAutomaticCleanup = false; // Disable for testing }); -
Example (Production with custom store):
// Production scenario: Implement IDeadLetterStore for your persistence layer public class MyEfCoreDeadLetterStore : IDeadLetterStore { private readonly MyDbContext _context; public MyEfCoreDeadLetterStore(MyDbContext context) => _context = context; public async Task AddAsync(IDeadLetterMessage message, CancellationToken ct = default) { _context.DeadLetterMessages.Add(MapToEntity(message)); await _context.SaveChangesAsync(ct); } // ... implement remaining interface methods } // Register with custom implementations services.AddEncinaDeadLetterQueue<MyEfCoreDeadLetterStore, MyDeadLetterMessageFactory>(options => { options.RetentionPeriod = TimeSpan.FromDays(30); options.EnableAutomaticCleanup = true; options.IntegrateWithRecoverability = true; options.OnDeadLetter = async (msg, ct) => await alertService.SendAlertAsync($"Message dead-lettered: {msg.RequestType}"); }); // Query and replay var stats = await manager.GetStatisticsAsync(); var result = await manager.ReplayAsync(messageId);
-
-
Low-Ceremony Sagas (Issue #41):
-
SagaDefinition.Create<TData>(sagaType)fluent API for defining sagas inline -
SagaStepBuilder<TData>withExecute()andCompensate()methods -
ISagaRunnerinterface for executing saga definitions -
SagaRunnerimplementation with full lifecycle management:- Sequential step execution with data flow between steps
- Automatic compensation in reverse order on failure
- Exception handling with compensation continuation
-
SagaResult<TData>record withSagaId,Data, andStepsExecuted -
Simplified overloads without
IRequestContextparameter -
Optional timeout configuration via
WithTimeout(TimeSpan) -
Auto-generated step names (
Step 1,Step 2, etc.) when not specified -
High-performance logging with
LoggerMessageattributes -
Full test coverage: unit, property-based, and contract tests
-
Automatic DI registration when
UseSagas = true -
Example:
var saga = SagaDefinition.Create<OrderData>("ProcessOrder") .Step("Reserve Inventory") .Execute(async (data, ct) => /* ... */) .Compensate(async (data, ct) => /* ... */) .Step("Process Payment") .Execute(async (data, ct) => /* ... */) .Compensate(async (data, ct) => /* ... */) .WithTimeout(TimeSpan.FromMinutes(5)) .Build(); // SagaResult<TData> contains IsSuccess, Data (final state), Error (if failed), // SagaId, and StepsExecuted count for observability var result = await sagaRunner.RunAsync(saga, initialData); if (result.IsSuccess) { // Saga completed successfully - continue business flow logger.LogInformation("Order {OrderId} processed. Steps: {Steps}", result.Data.OrderId, result.StepsExecuted); await notificationService.SendConfirmationAsync(result.Data); } else { // Saga failed and compensations ran - handle the failure logger.LogError("Order saga failed: {Error}", result.Error?.Message); await alertService.NotifyFailureAsync(result.SagaId, result.Error); }
-
-
Automatic Rate Limiting with Adaptive Throttling (Issue #40):
RateLimitAttributewith configurable properties:MaxRequestsPerWindow- Maximum requests allowed in the time windowWindowSizeSeconds- Duration of the sliding windowErrorThresholdPercent- Error rate threshold for adaptive throttling (default: 50%)CooldownSeconds- Duration to remain in throttled state (default: 30s)RampUpFactor- Rate of capacity increase during recovery (default: 1.5x)EnableAdaptiveThrottling- Toggle adaptive behavior (default: true)MinimumThroughputForThrottling- Minimum requests before error rate is calculated
IRateLimiterinterface withAcquireAsync,RecordSuccess,RecordFailure,GetState,ResetAdaptiveRateLimiterimplementation with:- Sliding window rate limiting algorithm
- State machine:
Normal→Throttled→Recovering→Normal - Thread-safe
ConcurrentDictionaryfor per-key state management - Automatic outage detection via error rate monitoring
- Gradual recovery with configurable ramp-up
RateLimitingPipelineBehavior<TRequest, TResponse>for automatic rate limitingRateLimitResultrecord struct withAllowed()andDenied()factory methodsRateLimitStateenum (Normal,Throttled,Recovering)EncinaErrorCodes.RateLimitExceedederror code- Automatic DI registration as singleton (shared state across requests)
- Comprehensive test coverage: 104 unit tests, 22 property tests, 22 contract tests, 10 guard tests, 4 load tests
- Performance benchmarks for rate limiter operations
-
AggregateTestBase for Event Sourcing testing (Issue #46):
AggregateTestBase<TAggregate, TId>base class for Given/When/Then testing patternAggregateTestBase<TAggregate>convenience class for Guid identifiersGiven(params object[] events)for setting up event historyGivenEmpty()for testing aggregate creation scenariosWhen(Action<TAggregate>)andWhenAsync(Func<TAggregate, Task>)for command executionThen<TEvent>()andThen<TEvent>(Action<TEvent>)for event assertionsThenEvents(params Type[])for verifying event sequenceThenNoEvents()for idempotency testingThenState(Action<TAggregate>)for state assertionsThenThrows<TException>()for exception assertionsGetUncommittedEvents()andGetUncommittedEvents<TEvent>()for direct access- Located in
Encina.Testing.EventSourcingnamespace - 75 tests covering unit, property, contract, and guard clause scenarios
-
Health Check Abstractions (Issue #35):
IEncinaHealthCheckinterface for provider-agnostic health monitoringHealthCheckResultstruct withHealthy/Degraded/UnhealthystatusEncinaHealthCheckabstract base class with exception handlingOutboxHealthCheckfor monitoring pending outbox messagesInboxHealthCheckfor monitoring inbox processing stateSagaHealthCheckfor detecting stuck/expired sagasSchedulingHealthCheckfor monitoring overdue scheduled messages- Configurable warning/critical thresholds for all health checks
- ASP.NET Core integration via
EncinaHealthCheckAdapter CompositeEncinaHealthCheckfor aggregating multiple health checks- Extension methods:
AddEncinaHealthChecks(),AddEncinaOutbox(),AddEncinaInbox(),AddEncinaSaga(),AddEncinaScheduling() - Kubernetes readiness/liveness probe compatible
-
Automatic Provider Health Checks (Issue #113):
ProviderHealthCheckOptionsfor configuring provider health checks (enabled by default)DatabaseHealthCheckabstract base class for database connectivity checks- Automatic health check registration when configuring Dapper providers:
PostgreSqlHealthCheckfor PostgreSQL (Encina.Dapper.PostgreSQL)MySqlHealthCheckfor MySQL/MariaDB (Encina.Dapper.MySQL)SqlServerHealthCheckfor SQL Server (Encina.Dapper.SqlServer)OracleHealthCheckfor Oracle Database (Encina.Dapper.Oracle)SqliteHealthCheckfor SQLite (Encina.Dapper.Sqlite)
- Automatic health check registration when configuring ADO.NET providers:
PostgreSqlHealthCheckfor PostgreSQL (Encina.ADO.PostgreSQL)MySqlHealthCheckfor MySQL/MariaDB (Encina.ADO.MySQL)SqlServerHealthCheckfor SQL Server (Encina.ADO.SqlServer)OracleHealthCheckfor Oracle Database (Encina.ADO.Oracle)SqliteHealthCheckfor SQLite (Encina.ADO.Sqlite)
EntityFrameworkCoreHealthCheckfor EF Core DbContext connectivity (Encina.EntityFrameworkCore)MongoDbHealthCheckfor MongoDB connectivity (Encina.MongoDB)RedisHealthCheckfor Redis/Valkey/KeyDB/Dragonfly/Garnet connectivity (Encina.Caching.Redis)RabbitMQHealthCheckfor RabbitMQ broker connectivity (Encina.RabbitMQ)KafkaHealthCheckfor Apache Kafka broker connectivity (Encina.Kafka)AzureServiceBusHealthCheckfor Azure Service Bus connectivity (Encina.AzureServiceBus)AmazonSQSHealthCheckfor Amazon SQS connectivity (Encina.AmazonSQS)NATSHealthCheckfor NATS server connectivity (Encina.NATS)MQTTHealthCheckfor MQTT broker connectivity (Encina.MQTT)MartenHealthCheckfor Marten/PostgreSQL event store connectivity (Encina.Marten)HangfireHealthCheckfor Hangfire scheduler status (Encina.Hangfire)QuartzHealthCheckfor Quartz.NET scheduler status (Encina.Quartz)- Configurable timeout, tags, and failure status
- Opt-out via
config.ProviderHealthCheck.Enabled = false - Integration tests with Testcontainers for all providers
SignalRHealthCheckfor SignalR hub connectivity (Encina.SignalR)GrpcHealthCheckfor gRPC service connectivity (Encina.gRPC)- Health check documentation in all provider READMEs
-
Modular Monolith support (Issue #57):
IModuleinterface for defining application modulesIModuleLifecycleinterface for modules with startup/shutdown hooksIModuleRegistryfor runtime module discovery and lookupModuleConfigurationfor fluent module registrationModuleLifecycleHostedServicefor automatic lifecycle managementAddEncinaModules()extension method for service registration- Automatic handler discovery from module assemblies
- Module ordering: start in registration order, stop in reverse (LIFO)
-
Module Health Checks (Issue #114):
IModuleWithHealthChecksinterface for modules to expose health checksIModuleHealthCheckinterface for module-specific health checks withModuleNamepropertyAddEncinaModuleHealthChecks()extension method for registering all module health checksAddEncinaModuleHealthChecks<TModule>()for registering specific module health checks- Automatic tagging with
encina,ready, andmodulestags - Integration with ASP.NET Core health check endpoints
-
Health Checks Integration Guide (Issue #115):
- Comprehensive documentation for integrating Encina with AspNetCore.HealthChecks.* packages
- Examples for microservice and modular monolith architectures
- Kubernetes probes configuration (liveness, readiness, startup)
- Recommended NuGet packages table for databases, caches, message brokers, cloud services
- Best practices for health check organization and tagging
- Located at
docs/guides/health-checks.md
-
Saga Not Found Handler support (Issue #43):
IHandleSagaNotFound<TMessage>interface for custom handling when saga correlation failsSagaNotFoundContextwithIgnore()andMoveToDeadLetterAsync()actionsSagaNotFoundActionenum (None,Ignored,MovedToDeadLetter)ISagaNotFoundDispatcherfor invoking registered handlersSagaErrorCodes.HandlerCancelledandSagaErrorCodes.HandlerFailederror codes- Automatic DI registration when
UseSagasis enabled
-
Delegate Cache Optimization benchmarks (Issue #49):
- New
CacheOptimizationBenchmarks.csfor validating cache performance improvements - Benchmarks for TryGetValue vs GetOrAdd patterns
- Type check caching comparison benchmarks
- New
-
Recoverability Pipeline (Issue #39):
- Two-phase retry strategy: immediate retries (in-memory) + delayed retries (persistent/scheduled)
RecoverabilityOptionswith configurable immediate retries (default 3), delayed retries (30s, 5m, 30m, 2h), exponential backoff, and jitterIErrorClassifierinterface withDefaultErrorClassifierfor classifying errors as Transient/Permanent/Unknown- Error classification by exception type (TimeoutException → Transient, ArgumentException → Permanent)
- Error classification by HTTP status codes (5xx → Transient, 4xx → Permanent)
- Error classification by message patterns ("timeout", "connection" → Transient)
RecoverabilityContextfor tracking retry state and historyFailedMessagerecord for dead letter queue handling with full contextRecoverabilityPipelineBehavior<TRequest, TResponse>pipeline behaviorIDelayedRetryScheduler,IDelayedRetryStore,IDelayedRetryMessageabstractionsDelayedRetrySchedulerandDelayedRetryProcessor(BackgroundService) implementationsOnPermanentFailurecallback for DLQ integration- Opt-in via
MessagingConfiguration.UseRecoverability = true - 64 unit tests covering all recoverability scenarios
Changed
-
Test Framework Migration from FluentAssertions to Shouldly (Issue #495):
- BREAKING: Replaced FluentAssertions with Shouldly across all 114 test projects
- Motivation: FluentAssertions adopted commercial licensing ($130/developer/year) in January 2025
- Shouldly remains MIT-licensed and is a mature, actively maintained library
- All assertion syntax migrated:
.Should().Be(x)→.ShouldBe(x).Should().BeTrue()→.ShouldBeTrue().Should().Throw<T>()→Should.Throw<T>(action).Should().HaveCount(n)→.Count.ShouldBe(n)or.ShouldHaveCount(n)FluentActions.Invoking(...).Should().Throw<T>()→Should.Throw<T>(() => ...)
- Custom
Encina.Testing.Shouldlypackage providesEither<TLeft, TRight>assertion extensions - Tests verified: 1000+ tests passing across core projects
-
Validation Architecture Consolidation (Issue #229) - Remove duplicate validation behaviors:
- BREAKING: Removed
Encina.FluentValidation.ValidationPipelineBehavior<TRequest, TResponse>(use centralizedEncina.Validation.ValidationPipelineBehavior<,>) - BREAKING: Removed
Encina.DataAnnotations.DataAnnotationsValidationBehavior<TRequest, TResponse>(use centralized behavior) - BREAKING: Removed
Encina.MiniValidator.MiniValidationBehavior<TRequest, TResponse>(use centralized behavior) - All validation now goes through
ValidationOrchestrator+ provider-specificIValidationProvider - DRY: Single
ValidationPipelineBehaviorinEncina.Validationnamespace - Consistent error handling across all validation providers
- BREAKING: Removed
-
Milestone Reorganization: Phase 2 (364 issues) split into 10 incremental milestones:
- v0.10.0 — DDD Foundations (31 issues)
- v0.11.0 — Testing Infrastructure (25 issues)
- v0.12.0 — Database & Repository (22 issues)
- v0.13.0 — Security & Compliance (25 issues)
- v0.14.0 — Cloud-Native & Aspire (23 issues)
- v0.15.0 — Messaging & EIP (71 issues)
- v0.16.0 — Multi-Tenancy & Modular (21 issues)
- v0.17.0 — AI/LLM Patterns (16 issues)
- v0.18.0 — Developer Experience (43 issues)
- v0.19.0 — Observability & Resilience (87 issues)
-
Performance: Optimized delegate caches to minimize reflection and boxing (Issue #49):
- TryGetValue-before-GetOrAdd pattern on ConcurrentDictionary to avoid delegate allocation on cache hits
- Cached
GetRequestKindtype checks to avoid repeatedIsAssignableFromcalls on hot paths - Applied to both
RequestDispatcherandNotificationDispatcher
-
BREAKING:
EncinaErrors.Create()andEncinaErrors.FromException()detailsparameter changed fromobject?toIReadOnlyDictionary<string, object?>?(Issue #34) -
BREAKING:
EncinaErrorExtensions.GetDetails()now returnsIReadOnlyDictionary<string, object?>instead ofOption<object> -
EncinaExceptioninternal class now storesDetailsasIReadOnlyDictionary<string, object?>instead ofobject? -
GetMetadata()is now an alias forGetDetails()(both return the same dictionary) -
Saga timeout support (Issue #38):
TimeoutAtUtcproperty inISagaStateinterfaceSagaStatus.TimedOutstatus constantSagaErrorCodes.Timeouterror codeTimeoutAsync()method inSagaOrchestratorto mark sagas as timed outGetExpiredSagasAsync()method inISagaStoreand all implementationsStartAsync()overload with timeout parameterDefaultSagaTimeoutandExpiredSagaBatchSizeoptions inSagaOptions- Full implementation across all providers (EF Core, Dapper, MongoDB, ADO.NET)
-
Regex timeout protection against ReDoS attacks (S6444) in caching and SignalR components
-
SQL injection prevention via
SqlIdentifierValidatorfor dynamic table names -
ROP assertion extensions in
Encina.TestInfrastructure.Extensions:ShouldBeSuccess()/ShouldBeRight()- Assert Either is RightShouldBeError()/ShouldBeLeft()- Assert Either is LeftShouldBeBottom()/ShouldNotBeBottom()- Assert Either default stateAllShouldBeSuccess()/AllShouldBeError()- Collection assertionsShouldContainSuccess()/ShouldContainError()- Collection contains assertionsShouldBeErrorWithCode(),ShouldBeValidationError(),ShouldBeAuthorizationError()- EncinaError assertions- Async variants:
ShouldBeSuccessAsync(),ShouldBeErrorAsync(),ShouldBeErrorWithCodeAsync()
-
Centralized messaging patterns with shared
Log.csandTransactionPipelineBehavior.cs -
Improved null handling in
InboxOrchestratorresponse deserialization
Fixed
- SonarCloud coverage detection with proper
SonarQubeTestProjectconfiguration - Benchmark CSV parsing and mutation report path detection
- EF Core PropertyTests compilation errors (Issue #116):
- Removed obsolete FsCheck 2.x files (
Generators.cs,OutboxStoreEFFsCheckTests.cs) - Fixed
SagaStatustype ambiguity inSagaStoreEFPropertyTests.cs - Fixed
SagaStatustype ambiguity inSagaStoreEFIntegrationTests.cs
- Removed obsolete FsCheck 2.x files (
Related Documents
MCP Server Specification: Grok Discussion Server
A standalone Model Context Protocol (MCP) server that enables intelligent discussions with Grok-4 AI, featuring context-aware conversations, baseline document generation, and response management.
C13.6: DAG Visualization & Workflow Security
> **Parent:** [C13 Monitoring, Logging & Anomaly Detection](C13-Monitoring-and-Logging)
🔐 Encryption & Hashing Reference Guide
**Data Security System - Complete Cryptographic Specification**
index
title: "Presidio: Open-Source Framework for PII Detection, Redaction & Anonymization"