Skip to content
CAI
Software that uses CAICheck a score

revoframework/Revo

48.5

Weak · 21 September 2026

26.8k

lines of production code

C#

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

Revo is a modular .NET framework for building event-driven, multi-tenant applications using CQRS and event sourcing. It provides a comprehensive infrastructure for managing domain models, asynchronous event processing, and background jobs, while supporting multiple data persistence strategies including Entity Framework Core, EF6, RavenDB, and SQL databases. The system also includes robust tooling for security, history tracking, and testing, all integrated within an ASP.NET Core environment.

How it got here

2017–2018 — Domain-driven architecture and ASP.NET Core integration

87 changes.

This period focused on establishing a comprehensive domain-driven architecture, introducing event sourcing, sagas, and read models alongside a new unified type versioning system. The framework was significantly expanded to support ASP.NET Core hosting, EF Core data access, and background job processing via Hangfire and Rebus.

2019–2022 — Infrastructure and tooling expansion

22 changes.

This period focused on expanding the framework's infrastructure with features like an in-memory job scheduler, automatic database migrations, and event stream upgrades. It also introduced a CLI tool for database management and enhanced the RavenDB provider with batch loading and fluent configuration. Additionally, the codebase added a sample application and improved AutoMapper integration.

Features

ASP.NET Core security module and user context implementation

Added AspNetCoreSecurityModule and AspNetCoreUserContext to provide ASP.NET Core-specific security integration. The new AspNetCoreUserContext implements the IUserContext interface, resolving the current user and their permissions by leveraging IClaimsPrincipalUserResolver and IHttpContextAccessor. This registers the user context in the DI container with task-scoped lifetime, enabling the framework to identify authenticated users and retrieve their permissions within the ASP.NET Core request pipeline.

Providers/AspNetCore/Revo.AspNetCore/Security · high confidence

Add EF6 data access provider implementation

The Revo framework now includes a new Entity Framework 6 (EF6) provider, enabling developers to use EF6 for data access, repositories, and in-memory testing. This adds a full suite of EF6-specific classes including \EF6CrudRepository\, \EF6DatabaseAccess\, and configuration extensions, allowing the application to persist and query data using the EF6 ORM alongside the existing EF Core support.

Providers/EF6/Revo.EF6 · high confidence

Add support for sequential (blocking) message processing in EasyNetQ subscriptions

The Revo.EasyNetQ module now allows subscriptions to be registered as 'blocking', meaning events are processed sequentially and the system waits for each message to complete before processing the next. This ensures original message ordering and prevents concurrent processing for specific event handlers. Users can enable this behavior via the new \isBlockingSubscriber\ configuration option when defining subscriptions.

Providers/EasyNetQ/Revo.EasyNetQ · high confidence

Added ASP.NET Core integration module

Introduced a new ASP.NET Core integration module that activates the ASP.NET Core and security modules via a configuration section. This enables the framework to load the AspNetCoreModule and AspNetCoreSecurityModule, providing the foundation for ASP.NET Core support within the application.

Providers/AspNetCore/Revo.AspNetCore/Configuration · high confidence

Added ASP.NET Core integration with custom Ninject scoping and activation

The Revo framework now supports ASP.NET Core via a new \Revo.AspNetCore\ provider. This adds a \RequestScopingMiddleware\ that manages Ninject DI scopes per HTTP request, and registers custom activators for controllers, SignalR hubs, and view components to ensure deterministic disposal of objects registered in the request or task context. The \RevoStartup\ class wires up these components, including \IHttpContextAccessor\ and \ILogger\ bindings, while explicitly calling \AddMvcCore()\ instead of \AddMvc()\.

Providers/AspNetCore/Revo.AspNetCore · high confidence

Added FakeRepository for testing with in-memory aggregate storage

A new FakeRepository implementation has been introduced in the Revo.Testing project to support unit testing. This in-memory repository tracks added, modified, and removed aggregates, allowing tests to verify domain logic without a database. The implementation includes methods for finding, getting, and querying aggregates, as well as handling transactional save operations and domain events.

Revo.Testing/Infrastructure/Repositories · high confidence

Added FakeUserContext for simplified security testing

A new FakeUserContext class has been added to the Revo.Testing.Security namespace to facilitate security testing. This class implements the IUserContext interface, allowing developers to easily mock user identity and permissions during unit tests without needing to configure complex authentication or role providers.

Revo.Testing/Security · high confidence

Added Rebus integration for event publishing and message handling

The Revo.Rebus provider now includes a new set of components to integrate with the Rebus message broker. This includes a RebusEventListener to collect and sequence domain events, a RebusEventMessageHandler to process incoming Rebus messages, and a RebusUnitOfWork to manage the transactional context for event publishing. Configuration is handled via a new UseRebus extension method that accepts a RebusConfigurer function, allowing users to define connection and routing settings programmatically rather than using XML configuration.

Providers/Rebus · high confidence

Added SQL baseline schemas for history tracking, event store, async events, and sagas

New SQL baseline scripts have been added for MSSQL, PostgreSQL, and SQLite, defining the initial database schema for Revo's core infrastructure. This includes tables for tracking entity changes (RHI), the event store (RES), asynchronous event queues (RAE), and saga metadata (REV). These scripts provide the foundational data structures required for these subsystems across different database providers.

Extensions/Revo.Extensions.History/Sql, Revo.Infrastructure/Sql · high confidence

Added batch-loading methods for in-memory repository

The in-memory data access layer now supports efficient batch loading of entities. New methods including GetManyAsync, FindManyAsync, and FindAllAsync have been added to the InMemoryCrudRepository, allowing consumers to retrieve multiple entities or all entities of a specific type in a single operation, improving performance for scenarios requiring bulk reads.

Revo.DataAccess/InMemory · high confidence

Added command validation via DataAnnotations

The Revo.Infrastructure module now includes a new validation pipeline for commands. A \CommandAttributeValidationFilter\ uses System.ComponentModel.DataAnnotations to validate command objects before execution, and a \ValidationInfrastructureModule\ registers this filter as a singleton. A corresponding \CommandValidationException\ is also provided for error handling.

Revo.Infrastructure/Properties, Revo.Infrastructure/Validation · high confidence

Added in-memory job scheduler implementation

The Revo.Infrastructure.Jobs.InMemory namespace now includes a complete in-memory job scheduling system. This includes the InMemoryJobScheduler for managing job execution, InMemoryJobSchedulerProcess for handling scheduled job timing, and InMemoryJobWorkerProcess for parallel job execution. The system supports immediate and delayed job scheduling with configurable retry policies and parallelism. Configuration is available via InMemoryJobsConfigurationSection and InMemoryJobsConfigurationExtensions.UseInMemoryJobs() for easy integration.

Revo.Infrastructure/Jobs/InMemory · high confidence

Added job scheduling and execution infrastructure

The Jobs module now includes a complete set of interfaces and implementations for scheduling and executing background jobs. New types include IJob, IJobHandler, IJobRunner, and IJobScheduler, along with command handlers for EnqueueJob and ScheduleJob. This enables the system to queue and run jobs asynchronously, with support for delayed execution and recurring schedules.

Revo.Infrastructure/Jobs · high confidence

Added support for executing lambda expressions as commands and queries

Users can now execute lambda expressions directly through the command bus, with the framework handling scoped resolution of parameter dependencies and committing the unit of work. New extension methods (SendLambdaCommandAsync) allow invoking lambda functions as if they were regular command handlers, supporting both void and result-returning operations with up to seven parameters.

Revo.Core/Commands/Lambda · high confidence

Added testing utilities for substitution and xUnit extensions

The Revo.Testing project now includes new helper classes to support testing workflows. A new \SubstituteDecorator\ class provides a static \For\<T\>\ method that uses NSubstitute to create spy objects for a given class. Additionally, an empty \XunitExtensions\ class has been added to the Revo.Testing.Extensions namespace, establishing a location for future xUnit-related test utilities.

Revo.Testing, Revo.Testing/Extensions · high confidence

Asynchronous event processing and queue management

The infrastructure now includes a complete asynchronous event processing pipeline, introducing classes such as AsyncEventProcessor, AsyncEventWorker, and AsyncEventQueueDispatcher to handle event queues. This adds support for both synchronous and asynchronous event dispatching, with configurable parallelism and retry policies. The system also introduces a locking mechanism (LockingAsyncEventWorker) to prevent concurrent processing of the same queue, and provides default sequencers (PerAggregateAsyncEventSequencer, PerTenantAsyncEventSequencer) for organizing events. Additionally, the AsyncEventExecutionCatchUp class ensures that event sources are caught up upon application startup, with an option to wait for completion or proceed asynchronously.

Revo.Infrastructure/Events/Async · high confidence

Automatic event projector discovery and registration

The framework now automatically discovers and registers event projectors by default, removing the need for manual configuration. This change introduces a new \ProjectorDiscovery\ component that scans for projector types and registers them in the DI container, simplifying the setup of event-driven read models.

Revo.Infrastructure/Projections · high confidence

Command and query authorization via attributes and filters

The Revo.Infrastructure.Security.Commands namespace now includes new classes and interfaces to enforce security on commands and entity queries. Users can apply the AuthenticatedAttribute or AuthorizePermissionsAttribute to command classes to require authentication or specific permissions. The CommandPermissionCache and CommandPermissionAuthorizer handle the actual authorization logic, while the EntityQueryAuthorizer and related interfaces (IEntityQueryFilter, IEntityQueryFilterFactory) allow filtering entity queries based on command context and user permissions.

Revo.Infrastructure/Security/Commands · high confidence

Initial support for Entity Framework Core data access and infrastructure

This change introduces the initial implementation of the Entity Framework Core provider for the Revo framework. It adds a complete data access layer including \EFCoreCrudRepository\ and \EFCoreReadRepository\ for standard CRUD and read operations, along with \EFCoreDatabaseAccess\ for raw SQL execution. The update also brings in configuration extensions (\UseAllEFCoreInfrastructure\) to enable EF Core for event stores, sagas, projections, and async events. Additionally, it provides a suite of EF Core conventions (e.g., snake\_case, lower\_case, prefixing) and a migration provider (\EFCoreDatabaseMigrationProvider\) to handle database schema updates.

Providers/EFCore · high confidence

Integration with Hangfire for background job processing

The Hangfire provider now integrates with the Revo framework to handle background jobs. Users can enable Hangfire via the new \UseHangfire\ configuration extension, which registers the \HangfireJobScheduler\ and \HangfireModule\ for dependency injection. The configuration section \HangfireConfigurationSection\ allows enabling the dashboard, configuring the job storage, and setting up recurring jobs. The \HangfireJobEntryPoint\ ensures that the task context is properly maintained and awaited during job execution.

Providers/Hangfire · high confidence

Introduce ADO.NET-based database migration providers for SQL Server, PostgreSQL, and SQLite

The system now supports executing database schema migrations via raw ADO.NET connections rather than relying solely on Entity Framework Core. New providers (AdoNetDatabaseMigrationProvider and its variants for MSSQL, PostgreSQL, and SQLite) allow database migrations to be applied using standard SQL commands, with each provider handling the specific SQL syntax for its database engine. This change enables database migration workflows that are independent of the ORM, offering a more direct and potentially faster path for schema versioning, while maintaining transactional integrity and event hooks for each migration step.

Revo.Infrastructure/DataAccess/Migrations/Providers · high confidence

Introduce DomainCoreModule and DomainException in Revo.Domain/Core

The Revo.Domain/Core area now includes a new DomainCoreModule that registers core domain services (ConventionEventApplyRegistratorCache, SagaConventionConfigurationCache, and EntityTypeManager) using Ninject, and introduces a DomainException class for domain-level error handling.

Revo.Domain/Core · high confidence

Introduce standalone Revo.Tools.DatabaseMigrator CLI tool

A new standalone .NET Core global tool (invokable as revo-dbmigrate) is added to the Tools directory, providing a command-line interface for database migrations. The tool supports upgrading and previewing migrations, loads assemblies in an isolated environment to resolve dependencies, and supports SQLite alongside Npgsql and SqlServer. It also introduces options to filter migrations by module (with wildcard support) and environment tags.

Tools · high confidence

Introduced buffered notification channels with configurable buffer governors and pipelines

Added new classes in the notification extension's buffering channel to support delayed, aggregated notification delivery. The system now uses an in-memory job scheduler to periodically process buffered notifications, selecting them via configurable buffer governors that identify buffers by string name rather than GUIDs. This allows for more flexible buffer management and ensures that projectors are registered before database migrations run.

Extensions/Revo.Extensions.Notifications/Channels/Buffering · high confidence

Introduced change tracking for entity attributes

Added a new change tracking system for entity attributes within the Revo.Extensions.History module. This includes the core ChangeTracker and EntityAttributeChangeLogger classes to record and persist attribute changes, along with supporting types like ChangeData, TrackedChange, and the associated interfaces and AutoMapper profiles to serialize and deserialize change records.

Extensions/Revo.Extensions.History/ChangeTracking · high confidence

Introduced event serialization and message factory infrastructure

Added new infrastructure components for event handling: an IEventSerializer interface and implementation that handles JSON serialization of events and metadata using configurable settings, and an IEventMessageFactory that constructs event messages with metadata from multiple providers. These changes support the broader event system by providing the underlying serialization and message creation mechanisms.

Revo.Infrastructure/Events · medium confidence

Introduced event-sourced base classes for aggregates, components, and entities

Added new base classes for event-sourced domain models: EventSourcedAggregateRoot, EventSourcedComponent, and EventSourcedEntity, along with the supporting AggregateState and IEventSourcedAggregateRoot interface. These classes provide a convention-based mechanism where state is derived from a sequence of domain events, allowing aggregates and their internal components/entities to publish and react to events while maintaining versioned state.

Revo.Domain/Entities/EventSourcing · high confidence

Introduced generic saga metadata storage and repository

Added new domain models (SagaMetadataKey, SagaMetadataRecord) and a repository (SagaMetadataRepository) to manage saga metadata. The repository provides methods to add sagas, find sagas by class ID or specific key-value pairs, retrieve metadata, and update keys, effectively replacing previous ad-hoc or generic event store implementations with a dedicated, structured approach to saga metadata persistence.

Revo.Infrastructure/Sagas/Generic · high confidence

Introduced new base entity classes for ORM persistence

Added a new hierarchy of base classes in Revo.Domain/Entities/Basic to support standard ORM persistence to relational databases. This includes BasicEntity for simple entities, BasicAggregateRoot for aggregate roots with versioning, and BasicClassEntity/BasicClassAggregateRoot which add a ClassId property for convenient RDBMS storage. These classes implement interfaces like IQueryableEntity and IRowVersioned, providing a foundation for entities that persist their visible state rather than just events.

Revo.Domain/Entities/Basic · high confidence

Introduced new saga infrastructure with convention-based configuration and event dispatching

Added a new saga subsystem in Revo.Infrastructure/Sagas that enables automatic saga lifecycle management through a convention-based configuration model. The change introduces a registry (ISagaRegistry) and a configuration loader (SagaConfigurationLoader) that scans for saga types and their event bindings. A new event listener (SagaEventListener) buffers and dispatches domain events to sagas, coordinating with the unit of work for transactional consistency. The implementation includes key components like KeySagaLocator for finding existing sagas by key, SagaEventDispatcher for handling events, and SagaRepository for persistence. This provides a structured way to define and manage sagas without manual wiring.

Revo.Infrastructure/Sagas · high confidence

Introduces a coordinated transaction and unit-of-work model for EF Core

The Revo.Core.Transactions namespace now includes a new coordinated transaction system, including the CoordinatedTransaction class and a suite of supporting interfaces (ITransaction, ITransactionCoordinator, ITransactionParticipant, IUnitOfWork, etc.). This change enables coordinated commits across EF Core and related components, ensuring that sync projections, event publishing, and async event dispatching are handled within the same transactional scope. Users will now interact with a unified UnitOfWork model for committing changes, which improves consistency when working with EF Core and event projections.

Revo.Core/Transactions · medium confidence

Introduction of convention-based saga implementation

The saga subsystem has been refactored to support convention-based saga definitions. New base classes, BasicSaga and EventSourcedSaga, are introduced to handle state persistence and event sourcing respectively. The system now scans for saga types implementing IConventionBasedSaga and uses the SagaEventAttribute to map domain events to handler methods. This allows developers to define sagas by simply adding the \[SagaEvent\] attribute to their event handler methods, removing the need for explicit registration or configuration of event-to-saga mappings.

Revo.Domain/Sagas · high confidence

New CommandApiController base class for ASP.NET Core

A new abstract base class, CommandApiController, has been added to the Revo.AspNetCore.Web namespace. This class inherits from ControllerBase and provides dependency-injected properties for ICommandBus and ICommandGateway, enabling derived controllers to easily access command handling infrastructure in ASP.NET Core applications.

Providers/AspNetCore/Revo.AspNetCore/Web · high confidence

New Todos sample application

A new sample application demonstrating Revo's capabilities is now available in the Examples/Todos directory. It includes domain models (Todo, TodoList), command and query message handlers, DTOs with AutoMapper profiles, read-model projections, and Razor Pages for the UI. The example showcases event sourcing, CQRS, and read-model projections using SQLite by default, with SQL scripts for MSSQL, PostgreSQL, and SQLite.

Examples/Todos/Revo.Examples.Todos · high confidence

New change-tracking data models for history extension

The History extension now includes new domain models to support change tracking: EntityAttributeData, which stores attribute key-value pairs as JSON, and TrackedChangeRecord, which records details of each tracked change including actor, entity identifiers, and change data. These models enable the system to record and retrieve historical state changes for entities.

Extensions/Revo.Extensions.History/ChangeTracking/Model · high confidence

New collection utilities and logging factory

Added a new Extensions class with a ToSeparatedString helper and an AsNotNull method that returns an empty enumerable instead of null. Introduced a custom MultiValueDictionary\<TKey, TValue\> implementation that supports adding ranges from IGrouping and IDictionary-like operations, replacing the deprecated System.Collections.Generic.MultiValueDictionary. Also added a GenericLoggerFactory that creates ILogger\<T\> instances from an ILoggerFactory.

Revo.Core/Collections · medium confidence

New domain event infrastructure and metadata extensions

The Revo.Domain/Events area introduces a new event sourcing architecture, including the AggregateEventRouter for publishing and replaying domain aggregate events, and a ConventionEventApplyRegistrator that uses reflection to automatically register event handlers. Additionally, MetadataExtensions are added to retrieve event metadata (such as publish date, store date, and tenant ID) as nullable values, and the DomainEvent base class is updated to include an AggregateId.

Revo.Domain/Events · high confidence

New entity and aggregate root infrastructure

Added new domain entity abstractions and infrastructure: the AggregateRoot base class with event publishing and versioning, the IAggregateRoot interface, and supporting types (IEntity, IComponent, IQueryableEntity, DomainClassInfo, EntityTypeManager, and DomainClassIdAttribute) to manage class IDs and type mappings.

Revo.Domain/Entities · high confidence

New entity data access interfaces and utilities

The Revo.DataAccess.Entities namespace now includes a comprehensive set of interfaces and helper classes to support data access operations. This includes the IReadRepository and ICrudRepository interfaces, which define methods for retrieving and managing entities, including new batch retrieval methods like GetManyAsync and FindManyAsync. The update also introduces the IAsyncQueryableResolver interface and corresponding QueryableRepositoryExtensions to handle asynchronous query operations, alongside utility classes like EntityExpressionUtils and RepositoryHelpers to support these new capabilities.

Revo.DataAccess/Entities · high confidence

New event message and publishing infrastructure in Revo.Core.Events

The Revo.Core.Events namespace now includes a full suite of new types to support event publishing and buffering. This includes the EventBus and IEventBus for dispatching messages, along with supporting classes like EventMessage, EventMessageDraft, and their associated interfaces. A PublishEventBuffer and its factory are introduced to manage and flush event messages. Additionally, metadata handling is expanded with new classes such as JsonMetadata, LayeredMetadata, and FilteringMetadata, while BasicEventMetadataNames is added to define standard metadata keys.

Revo.Core/Events · high confidence

New event stream upgrade system for on-the-fly event migration

Revo now includes a built-in mechanism to upgrade event streams on-the-fly when loading aggregates. Developers can implement the new IEventUpgrade interface (or extend EventUpgrade\<TAggregate\>) to define how old event types are transformed into new ones. The system auto-discovers all IEventUpgrade implementations in the application, applies them via the EventStreamUpgrader, and handles sequence number and metadata updates automatically. This allows existing event data to be migrated seamlessly without manual intervention.

Revo.Infrastructure/Events/Upgrades · high confidence

New read model base classes and interfaces for entity and event tracking

The Revo.Domain.ReadModel namespace now includes new base classes and interfaces to support read model implementations. EntityReadModel and EntityView provide abstract foundations for entities with Id and Version properties, while EventEntityReadModel adds tracking of the last projected event number for concurrency control. Additionally, interfaces like IEventNumberVersioned and IClassEntityReadModel are introduced to support arbitrary versioning and class-specific read models. These changes enable more flexible read model designs, particularly for scenarios requiring manual row versioning or event stream synchronization.

Revo.Domain/ReadModel · high confidence

New repository and aggregate store architecture for CRUD and event-sourced aggregates

The repository layer has been restructured to support two distinct aggregate storage strategies: a standard CRUD store for database-backed aggregates and an event-sourced store for event-sourced aggregates. This change introduces new interfaces (IAggregateStore, IRepository) and implementations (CrudAggregateStore, EventSourcedAggregateStore) that handle saving changes, publishing events, and managing entity lifecycles. The Repository class now delegates to the appropriate store based on the aggregate type, enabling optimized batch loading and transactional safety for both aggregate types.

Revo.Infrastructure/Repositories · high confidence

New testing helpers for event-sourced entities

The Revo.Testing.Infrastructure namespace now includes new utilities for testing event-sourced aggregates. EventExtensions provides a ToMessageDraft method to convert events into message drafts, and an overload of ToAggregateEventMessages that automatically populates metadata such as stream sequence numbers, aggregate class IDs, and timestamps. Additionally, EventSourcedEntityTestingHelpers introduces AssertEvents and AssertAllEvents extension methods that allow developers to verify the sequence and content of domain events generated by an aggregate root, supporting both simple event assertions and custom event-level assertions.

Revo.Testing/Infrastructure · high confidence

New unified type versioning system

A new type versioning system has been introduced, providing a unified way to manage and retrieve versioned types. This includes new interfaces (ITypeExplorer, ITypeIndexer, IVersionedTypeRegistry) and their implementations (TypeExplorer, TypeIndexer, VersionedTypeRegistry), along with supporting classes (VersionedType, VersionedTypeId, TypeVersionAttribute). The system allows for querying all types, finding types by name and version, and caching results for performance. This change enables better management of type versions within the core library.

Revo.Core/Types · high confidence

New value object base classes and collection wrappers

The Revo.Core library now includes a new ValueObject\<T\> base class that provides value-based equality, hashing, and string representation. This includes wrappers for immutable collections (ListAsValue, SetAsValue, DictionaryAsValue) that implement value semantics for use within value objects, and a SingleValueObject\<T, TValue\> class with a corresponding JSON converter for serializing single-value types.

Revo.Core/ValueObjects · high confidence

RavenDB projection subsystem and event listener implementation

The RavenDB provider now includes a complete projection subsystem, introducing the \RavenProjectionSubSystem\ and \RavenProjectionEventListener\ to handle event processing. This includes a new \IRavenEntityEventProjector\ interface, a \RavenEntityEventToPocoProjector\ for mapping events to POCOs, and a \RavenProjectorDiscovery\ class that enables automatic discovery and registration of projectors. The \RavenProjectionsModule\ registers these components within the Ninject DI container, wiring up the event listener and sequencer to ensure correct tenant context and transactional safety during projection execution.

Providers/RavenDB/Revo.RavenDB/Projections · high confidence

RavenDB provider module initialization and repository binding

The Revo.RavenDB provider now includes a RavenModule that configures the RavenDB client (IDocumentStore) as a singleton and binds IAsyncDocumentSession to the task scope. It registers RavenCrudRepository and, when configured as the primary repository, also registers ICrudRepository and IReadRepository implementations, enabling the application to persist data to RavenDB.

Providers/RavenDB/Revo.RavenDB · high confidence

Behavioural changes

ASP.NET Core integration and Hangfire job resolution fixes

The ASP.NET Core provider introduces new components to integrate Revo with the ASP.NET Core hosting environment and Hangfire background job processing. An AspNetCoreEnvironmentProvider bridges the ASP.NET Core IWebHostEnvironment to Revo's environment abstraction. A HangfireJobActivator and HangfireStartupConfigurator are added to resolve Hangfire jobs via the Ninject DI container, with configuration options to enable the Hangfire dashboard and processing server. Additionally, a UserActorContext implementation provides the current user's actor context for ASP.NET Core requests.

Providers/AspNetCore/Revo.AspNetCore/Core · high confidence

Added batch loading of event-sourced aggregates via new repository methods

The RavenDB provider now supports efficient batch retrieval of aggregates. New methods including IReadRepository.GetManyAsync, FindManyAsync, and the implementation in RavenCrudRepository allow fetching multiple entities by their IDs in a single operation. Additionally, FindAllAsync has been updated to return an array instead of an IList, and convenience overloads for Guid-based IDs have been added to streamline common access patterns.

Providers/RavenDB/Revo.RavenDB/DataAccess · medium confidence

AutoMapper integration refactored with optional configuration and profile discovery

The Revo.Extensions.AutoMapper module has been refactored to separate core dependency on AutoMapper, introducing explicit profile discovery and an optional configuration action. Users can now enable automatic profile discovery via the new \AddAutoMapperExtension\ extension method, which registers the \AutoMapperInitializer\ and \AutoMapperModule\ in the DI container. The \AutoMapperConfigurationSection\ allows users to pass an \Action\<IMapperConfigurationExpression\>\ to customize the AutoMapper \MapperConfiguration\ (e.g., adding expression mapping or custom service resolution). This change isolates the automatic registration of profiles into the new \Revo.Extensions.AutoMapper\ package, ensuring that the core framework remains decoupled from AutoMapper-specific logic.

Extensions/Revo.Extensions.AutoMapper · medium confidence

Automatic database migration execution on startup

Database migrations are now applied automatically when the application starts in development mode. The new DatabaseMigrationExecutionHook implements IApplicationStartingListener and triggers the migration process via a command handler, ensuring that the database schema is up-to-date before the application fully initializes. This behavior is controlled by the ApplyMigrationsUponStartup configuration option, which defaults to true in development environments.

Revo.Infrastructure/DataAccess/Migrations · high confidence

Centralized infrastructure configuration via new InfrastructureConfigurationSection

The Revo.Infrastructure module now provides a unified configuration entry point, InfrastructureConfigurationExtensions, which registers core infrastructure components including the in-memory job scheduler, async event pipeline, database migrations, tenancy, and sagas. This replaces the previous scattered registration approach with a single, section-based configuration model that allows users to enable or disable features like sagas and configure the event pipeline and database migrations through a dedicated section.

Revo.Infrastructure · medium confidence

Enforced tenant data isolation with configurable access for null tenants

The tenancy infrastructure now enforces strict data isolation by default, preventing null (unauthenticated) tenants from accessing other tenants' data. This is controlled by the new \NullTenantCanAccessOtherTenantsData\ configuration option in \TenancyConfiguration\. The \TenantRepositoryFilter\ now throws an \InvalidOperationException\ when a null tenant attempts to add, modify, or delete tenant-scoped entities, and filters out cross-tenant data in queries. This change ensures that multi-tenant applications correctly isolate data by default, while allowing specific configurations to relax these restrictions if needed.

Revo.Infrastructure/Tenancy · high confidence

EntityDto now implements IHasId\<Guid\>

The base EntityDto class now implements the IHasId\<Guid\> interface, providing a standardized way to access the unique identifier of domain entities. This change ensures that all DTOs inheriting from EntityDto automatically expose a Guid-based Id property, aligning the domain model with the system's identity contract.

Revo.Domain/Dto · medium confidence

Explicit registration of History and Notifications extensions

Added configuration extensions for the History and Notifications modules, allowing developers to explicitly register and configure these features via \AddHistoryExtension\ and \AddNotificationsExtension\ respectively. This change introduces new configuration sections (\HistoryConfigurationSection\ and \NotificationsConfigurationSection\) that control whether change tracking and notifications are active, enabling more granular control over these capabilities in the application setup.

Extensions/Revo.Extensions.History/Configuration, Extensions/Revo.Extensions.Notifications/Configuration · high confidence

FakeClock now uses AsyncLocal for thread-safe time manipulation

The FakeClock implementation has been refactored to use AsyncLocal storage instead of ThreadLocal, ensuring that changes to the fake clock's value are atomic and thread-safe. This change allows the FakeClock to be used reliably in asynchronous contexts without race conditions, improving the stability of time-based tests.

Revo.Testing/Core · medium confidence

Introduce programmatic configuration for RavenDB data access and projections

The RavenDB provider now uses a new fluent API for setup, replacing previous XML-based or manual wiring. Developers can now call UseRavenDataAccess and UseRavenProjections to configure the database connection, designate it as the primary repository, and enable automatic projector discovery (enabled by default). This simplifies setup by removing the need for manual DI registration or XML configuration files.

Providers/RavenDB/Revo.RavenDB/Configuration · medium confidence

Introduce tenant-owned base classes and events

Added a new set of base classes and interfaces in the Revo.Domain/Tenancy namespace to support tenant-scoped domain models. This includes TenantAggregateRootCreated event, ITenantOwned interface, and abstract base classes for aggregates (TenantBasicAggregateRoot, TenantBasicClassAggregateRoot, TenantEventSourcedAggregateRoot) and read models (TenantReadModelBase, TenantEntityReadModel, TenantClassEntityReadModel, TenantEntityView) that all include a TenantId property to associate resources with a specific tenant.

Revo.Domain/Tenancy · medium confidence

Introduced new mail notification channel implementation

The mail notification channel has been refactored to use a new, decoupled architecture. A new \IMailNotificationFormatter\ interface and \MailBufferedNotificationChannel\ class handle message formatting and job scheduling, while \SmtpMailNotificationSender\ provides the actual SMTP sending logic. Configuration is now handled via \MailNotificationConfigurationExtensions\ and \MailNotificationsModule\, allowing for more flexible setup of the mail sender factory.

Extensions/Revo.Extensions.Notifications/Channels/Mail · medium confidence

Introduces task-based scoping for dependency injection

The framework now supports a new 'task scope' for dependency injection, allowing services to be scoped to the execution of a specific task or async operation rather than just the HTTP request. This is implemented via the new \TaskContext\ and \NinjectBindingExtensions.InTaskScope\ API, which uses \AsyncLocal\ to flow context across async boundaries. This change ensures that objects registered in the task context are deterministically disposed, fixing issues where services were incorrectly resolved in jobs that use async tasks.

Revo.Core/Core · high confidence

New programmatic configuration API for core and kernel setup

The framework now requires components to be programmatically configured and set-up using the newly introduced API (RevoConfiguration, CoreConfigurationSection, KernelConfigurationSection) prior to bootstrapping. This change introduces a structured configuration system that allows developers to explicitly configure core modules, kernel modules, and advanced settings via extension methods like ConfigureCore and ConfigureKernel, replacing previous implicit or attribute-based setup mechanisms.

Revo.Core/Configuration · high confidence

New security abstractions and null implementations for authorization

The security layer now introduces several new interfaces and classes to handle user resolution, permission matching, and authorization checks. This includes \IUser\, \IUserContext\, \IClaimsPrincipalUserResolver\, \IUserPermissionAuthorizer\, \IUserPermissionResolver\, \IPermissionAuthorizationMatcher\, \IPermissionTypeIndexer\, and \IPermissionTypeRegistry\. Alongside these, concrete implementations like \UserPermissionAuthorizer\, \PermissionAuthorizationMatcher\, \PermissionTypeIndexer\, and \PermissionTypeRegistry\ are added. Additionally, \NullClaimsPrincipalUserResolver\ and \NullUserPermissionResolver\ are provided to disable security checks when \UseNullSecurityModule\ is enabled in \SecurityConfiguration\. These changes support a more flexible and decoupled approach to managing permissions and user context within the core framework.

Revo.Core/Security · medium confidence

Notification buffers, pipelines, and governors are now identified by string names

The notification system has been refactored to use arbitrary string names to identify notification buffers, pipelines, and governors, replacing the previous GUID-based identification. This change provides greater flexibility in configuring and managing notification processing components, as evidenced by the new \NotificationBuffer\ model which now includes \Name\, \PipelineName\, and \GovernorName\ string properties. This is a breaking change for existing users who relied on the previous GUID-based identification.

Extensions/Revo.Extensions.Notifications/Model · medium confidence

Notification buffers, pipelines, and governors now use string names instead of GUIDs

The SQL schema for the Revo.Extensions.Notifications module has been updated to replace GUID-based identifiers for notification buffers, pipelines, and governors with arbitrary string names. This change allows for more flexible identification and management of these components within the notification system, as reflected in the new baseline SQL scripts for PostgreSQL, MSSQL, SQLite, and the migration script for PostgreSQL.

Extensions/Revo.Extensions.Notifications/Sql · high confidence

Overhauled command bus with middleware pipeline and automatic handler discovery

The command bus internals have been refactored to support a flexible middleware pipeline, allowing for features like automatic command handler discovery and execution options (such as auto-committing the Unit of Work or overriding the tenant context). The framework now automatically discovers and registers command handlers by default, and provides a new \CommandExecutionOptions\ API for configuring command execution behavior.

Revo.Core/Commands · high confidence

Refactored async event queue implementation

The async event queueing mechanism has been refactored to improve performance and correctness. The new implementation in Revo.Infrastructure/Events/Async/Generic introduces dedicated entities (AsyncEventQueue, QueuedAsyncEvent, EventSourceState) and managers to handle event dispatching more efficiently. This change includes optimizations for handling large numbers of queues and fixes a bug where async events might occasionally be enqueued twice during EF Core's coordinated transaction. Additionally, the code now ensures that external events and events published by non-event-sourced aggregates are not stored to the database if they are not dispatched to any async event queues, reducing unnecessary database writes.

Revo.Infrastructure/Events/Async/Generic · medium confidence

Refactored database initialization into a modular, dependency-aware system

The database initialization process has been restructured into a modular system that discovers, sorts, and executes initializers based on explicit dependencies. A new \DatabaseInitializerLoader\ coordinates the process, using a \DatabaseInitializerDependencySorter\ to respect \InitializeAfterAttribute\ ordering, ensuring that dependent initializers run in the correct sequence. This change improves reliability by preventing race conditions during startup and allows for more complex initialization scenarios, such as seeding static classifiers or handling event-sourced aggregates, while maintaining thread safety.

Revo.Infrastructure/DataAccess · medium confidence

Refactored event store implementation to use a generic, EF Core-based architecture

The event store infrastructure has been refactored to replace the previous EF6/legacy implementations with a new generic architecture built on Entity Framework Core. This change introduces new core classes such as EventStore, ExternalEventStore, and their associated interfaces (IEventStore, IExternalEventStore) and data models (EventStream, EventStreamRow). The refactoring aligns the event store with the broader framework's move to .NET 6.0 and EF Core 6.0, providing a more consistent and modern foundation for event sourcing and external event handling.

Revo.Infrastructure/EventStores · high confidence

Refactored notification system with new interfaces and serialization

The notification extension has been refactored to support a more modular architecture. New interfaces including INotification, IGroupedNotifications, INotificationBus, INotificationChannel, INotificationSerializer, and INotificationTypeCache define the core contract. The NotificationBus now routes notifications to appropriate channels, while the NotificationSerializer handles JSON serialization using consistent settings. The NotificationTypeCache discovers all notification types via the type explorer. These changes enable better separation of concerns and improved testability within the notification system.

Extensions/Revo.Extensions.Notifications · high confidence

Security infrastructure module registers DI bindings for entity query authorization and command permissions

A new Ninject module, SecurityInfrastructureModule, has been added to Revo.Infrastructure/Security. It registers the entity query authorizer and filter factories within a task scope, binds the command permission cache as a singleton, and registers the command permission authorizer as a transient pre-command filter. This change introduces the core security infrastructure bindings for query authorization and command-level permission checks.

Revo.Infrastructure/Security · medium confidence

Fixes

Release 1.38.2 fixes repeatable SQL migrations not being transitively reapplied

Repeatable SQL migrations are now correctly re-applied when a (transitive) dependency changes, ensuring the database schema stays in sync with the active tag-compatible variant. This addresses an issue where repeatable modules were not being ordered by dependencies-first, leading to potential schema inconsistencies.

(repo-wide) · high confidence

Test coverage

Added test configuration for Revo.Infrastructure.Tests; Added tests for InMemoryCrudRepository behavior; Added tests for Lambda command handling; Added tests for ValueObject equality and serialization; Added tests for application lifecycle configuration and notification; Added tests for async event queue management and message creation; Added tests for database initializer sorting and loading; Added tests for database migration components; Added tests for event message creation, serialization, and metadata providers; Added tests for event stream upgrade functionality; Added tests for permission authorization logic; Added tests for saga convention scanning and basic saga handling; Added tests for the generic saga metadata repository; Added tests for the in-memory job scheduler and job runner; Added tests for the unified type versioning system; Added unit tests for AggregateRoot behavior; Added unit tests for EF6 in-memory data access components; Added unit tests for MultiValueDictionary and GenericLoggerFactory; Added unit tests for Unit of Work transaction management; Added unit tests for command bus pipeline and middleware components; Added unit tests for command permission authorization and caching; Added unit tests for event bus and metadata classes; Added unit tests for event handling infrastructure; Added unit tests for generic event store and external event source catch-up; Added unit tests for history change tracking components; Added unit tests for projection infrastructure; Added unit tests for repository and aggregate store implementations; Added unit tests for saga infrastructure components; Added unit tests for tenancy context and repository filtering; Added unit tests for the Revo configuration system; Added unit tests for the Revo.EasyNetQ provider; Added unit tests for the TodoList domain model; Added unit tests for the async event processing pipeline; Added unit tests for the notification buffering and processing pipeline; Disable parallelization of xUnit tests; Disables parallelization of xUnit tests.

Dependencies

Upgrade to .NET 10.0 and update dependencies

The project files have been updated to target .NET 10.0. This includes upgrading the core framework dependencies to version 10.0.0, such as Microsoft.EntityFrameworkCore and Microsoft.Extensions.DependencyInjection. Other dependencies have also been updated, including AutoMapper 14.0.0, Hangfire 1.8.22, and Rebus 8.9.0.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Score

  • CAI 47 → 49 (+2.0)
  • Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 50 → 48 (-1.8)
  • Architecture 78 → 78 (+0.1)
  • Maturity 55 → 55 (+0.1)
  • Readiness 43 → 41 (-1.4)
  • Security 74 → 78 (+3.3)
  • Domain Modelling 60 → 52 (-7.1)
  • Event Sourcing 82 (new)

Resolved (22)

  • Bounded contexts not declared
  • Duplicated block (11 lines × 3) (Revo.Infrastructure/Projections/EntityEventProjector.cs)
  • Duplicated block (15 lines × 2) (Revo.Infrastructure/Projections/EntityEventProjector.cs)
  • Duplicated block (27 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • Duplicated block (27 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • Duplicated block (5 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • Duplicated block (6 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Model/EntityTypeDiscovery.cs)
  • Duplicated block (7 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • High CVE: System.Security.Cryptography.Xml 9.0.0
  • No exposed public API
  • Off-boarding risk: anonymized user #1
  • The concept of a soft-delete flag is named 'IsDeleted' in the Saga test class, but 'IsDeleted' is also used for the IAggregateRoot interface. While this is consistent, the test class naming 'Saga1' is a generic placeholder name that differs from the specific domain concept 'Saga1' in the test, which is acceptable for tests but worth noting if it appears in production code.
  • The identifier for a Saga is referred to as 'Id' in the test class 'Saga1' but as 'Keys' in the 'ISaga' interface. This suggests a potential inconsistency between the concrete implementation/test and the interface definition.
  • …and 2 more

New (64)

  • CommentedOutCode (Extensions/Revo.Extensions.History/ChangeTracking/EntityAttributeChangeLogger.cs)
  • CommentedOutCode (Extensions/Revo.Extensions.History/ChangeTracking/Model/EntityAttributeData.cs)
  • CommentedOutCode (Providers/EF6/Revo.EF6/DataAccess/Model/CustomStoreConvention.cs)
  • CommentedOutCode (Providers/EF6/Revo.EF6/DataAccess/Model/CustomStoreConvention.cs)
  • CommentedOutCode (Revo.Infrastructure/Events/Async/AsyncEventSequencer.cs)
  • Cross-context type IActorContext (Revo.Core → Extensions)
  • Cross-context type IActorContext (Revo.Core → Revo.Infrastructure)
  • Cross-context type IAggregateStore (Revo.Infrastructure → Providers)
  • Cross-context type IAggregateStore (Revo.Infrastructure → Providers)
  • Cross-context type IEnvironment (Revo.Core → Revo.Infrastructure)
  • Dead code: DelegatingTagHelperActivator (Providers/AspNetCore/Revo.AspNetCore/AspNetCoreMvcExtensions.cs)
  • Dead code: XunitExtensions (Revo.Testing/Extensions/XunitExtensions.cs)
  • Duplicated block (11 lines × 2) (Providers/EF6/Revo.EF6/Configuration/EF6InfrastructureConfigurationSection.cs)
  • Duplicated block (12 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Model/EntityTypeDiscovery.cs)
  • Duplicated block (13–16 lines × 4) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • Duplicated block (14 lines × 3) (Revo.Infrastructure/Projections/EntityEventProjector.cs)
  • Duplicated block (19 lines × 2) (Revo.Infrastructure/Projections/EntityEventProjector.cs)
  • Duplicated block (19 lines × 3) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • Duplicated block (32–35 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • Duplicated block (33–36 lines × 2) (Providers/EF6/Revo.EF6/DataAccess/Entities/EF6CrudRepository.cs)
  • …and 44 more

API surface

  • Unchanged — 5 HTTP endpoints

Architecture

  • Containers 0 added · 0 removed · contexts 2 added · 0 removed · edges 7 added · 0 removed

Added bounded contexts (2)

  • Revo.Core
  • Revo.Infrastructure

Added dependency edges (7)

  • Examples → Revo.Core
  • Examples → Revo.Infrastructure
  • Extensions → Revo.Core (coupling)
  • Extensions → Revo.Infrastructure
  • Revo.Domain → Revo.Core
  • Revo.Infrastructure → Revo.Core (coupling)
  • Revo.Infrastructure → Revo.Domain

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

revoframework/Revo was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 7c04d8d9e12899db617bb8f09fa76fb1eaca36b2 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-28e75b8e3254.