Skip to content
CAI
Software that uses CAICheck a score

si-informational-systems/Rosetta

54.9

Adequate · 3 October 2026

2.8k

lines of production code

F#

primary language

2

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

SI.Rosetta is an F\# framework for building event-sourced and state-based aggregate systems with support for EventStoreDB, RavenDB, and MongoDB. It provides infrastructure for managing aggregate state persistence, projecting events into read models, and handling command execution. The system includes dedicated test kits for validating aggregates and projections, along with tooling like Visual Studio templates to simplify development.

Features

Added ObjectComparer for deep object comparison in test kits

The SI.Rosetta.TestKit.ObjectComparer module introduces a new utility for performing deep comparisons between two objects of the same type. This tool recursively inspects primitive types, strings, DateTime values, collections, and complex objects (including their public properties and fields), while explicitly handling circular references to prevent infinite recursion. It returns an empty string if objects are equal or a detailed report of all differences found, supporting the new aggregates and projections test kits.

SI.Rosetta.TestKit.ObjectComparer · high confidence

Added Visual Studio item template for generating SI.Rosetta F\# aggregates

Developers can now use a new Visual Studio item template to scaffold a complete SI.Rosetta aggregate structure in F\# projects. The template generates three files—\{Name}AggregateState.fs\, \{Name}Aggregate.fs\, and \{Name}AggregateHandler.fs\—providing base classes and default implementations for state, command execution, and async command handling. Installation is supported via provided batch and PowerShell scripts that copy the template files to the Visual Studio 2022 item templates directory, or manually by placing the folder in the user's templates path.

SI.Rosetta.Aggregates.Template · high confidence

Added factory modules for initializing EventStore, MongoDB, and RavenDB clients

New factory modules have been introduced in the persistence layer to centralize the creation and initialization of database clients. The EventStore factory now handles client initialization and projection management client setup using configuration values. The MongoDB factory introduces a configuration record and helper methods to generate connection strings with optional authentication and database names. The RavenDB factory provides a robust document store initializer that supports custom conventions, certificate-based authentication, and automatic database creation if it does not exist.

SI.Rosetta.Persistence.EventStore, SI.Rosetta.Persistence.MongoDB, SI.Rosetta.Persistence.RavenDB · high confidence

Added projections test kit with in-memory stubs

The SI.Rosetta.Projections.TestKit package now provides a test kit for validating projections. It includes an in-memory projection store (TestKitProjectionStore) that implements IProjectionsStore, INoSqlStore, and ISqlStore, allowing tests to run without a real database. A TestKitBase class simplifies writing projection tests by handling service registration (including a StubCheckpointStore and TestKitSubscriptionFactory) and providing Given/Then methods for event sourcing and assertion. An IdValidator ensures only supported ID types (string, int, int64, Guid) are used.

SI.Rosetta.Projections.TestKit · high confidence

MongoDB support for checkpoint and projection persistence

Added MongoDB implementations for the \ICheckpointStore\ and \IProjectionsStore\ interfaces, enabling users to persist event-sourced state and checkpoints in MongoDB. The \MongoDbCheckpointStore\ handles checkpoint upserts with retry logic, while \MongoDbProjectionsStore\ provides document storage, loading, and deletion with support for unit-of-work transactions (using \WriteConcern.WMajority\) and automatic retries on transient MongoDB errors.

SI.Rosetta.Projections.MongoDB · high confidence

New Aggregates Test Kit for validating command handlers

The SI.Rosetta.Aggregates.TestKit package is now available, providing a structured testing framework for aggregate command handlers. It includes a \TestKitBase\ class that supports a Given-When-Then workflow, allowing users to seed initial events, execute commands, and verify both produced and published events against expected outcomes. The kit features an in-memory repository (\TestKitAggregateRepository\) that supports both event-sourced and state-based repositories, and includes detailed output formatting to help diagnose test failures by comparing expected versus actual event structures.

SI.Rosetta.Aggregates.TestKit · high confidence

RavenDB persistence layer for state-based aggregates

The SI.Rosetta.Aggregates.RavenDB package now provides a concrete implementation of the state-based aggregate repository interface using RavenDB. This new RavenDBAggregateRepository enables users to persist and retrieve aggregate states by loading and storing document data, supporting generic aggregate types and their associated states within the RavenDB document store.

SI.Rosetta.Aggregates.RavenDB · high confidence

Rosetta 1.23 introduces MongoDB support and expanded test infrastructure

The framework now supports MongoDB for projection persistence alongside existing RavenDB and EventStoreDB integrations, allowing users to store read models in MongoDB. This release also adds dedicated TestKit projects for both Aggregates and Projections to simplify BDD testing, introduces a new aggregate template for scaffolding, and updates the solution structure with new persistence and test projects while removing the legacy Test.DTOs project.

(repo-wide) · high confidence

Removals

Removal of F\# EventStore serialization module

The ESSerialization module, which provided logic for serializing and deserializing F\# discriminated union events to and from EventStore using Newtonsoft.Json, has been removed from the codebase.

SI.Rosetta.Serialization.EventStore · high confidence

Behavioural changes

Aggregates now support versioned state and optional event sourcing

The aggregate model has been refactored to support both event-sourced and state-based persistence patterns. The \IAggregateRepository\ now returns an \Option\ type for \GetAsync\, allowing callers to handle missing aggregates explicitly without null checks, and accepts a \long\ (int64) version parameter. \AggregateState\ and \Aggregate\ types now use \int64\ for versioning and expose state via generic parameters in \AggregateHandler\, enabling more type-safe command execution. New interfaces \IEventSourcedAggregateRepository\ and \IStateBasedAggregateRepository\ inherit from the base repository to distinguish persistence strategies.

SI.Rosetta.Aggregates · high confidence

Event-sourced repository now returns Option types and uses generic state parameters

The EventStoreAggregateRepository has been updated to support generic aggregate state parameters, allowing the repository to work with specific state types rather than relying on reflection-based factory creation. Additionally, the GetAsync method now returns an Option type (Some aggregate or None) instead of null, improving type safety and eliminating the need for null literal handling in consumer code.

SI.Rosetta.Aggregates.EventStore · high confidence

Improved async context handling in EventStore projections hosted service

The EventStoreProjectionsHostedServiceInstance now uses ConfigureAwait(false) for all asynchronous operations, including projection creation and execution. This change ensures that the code does not capture and marshal back to the original synchronization context, which can improve scalability and prevent potential deadlocks in hosted service scenarios. Additionally, the dependency on IJSProjectionsFactory has been updated to IESCustomJSProjectionsFactory, reflecting a specific interface adjustment for custom JavaScript projections.

SI.Rosetta.Projections.HostBuilder/HostedServiceInstances · high confidence

Person aggregate refactored to support event sourcing and new commands

The Person aggregate in the test kit has been updated to align with the framework's shift towards supporting both state-based and event-sourced patterns. The PersonAggregateHandler now explicitly uses IEventSourcedAggregateRepository and includes the PersonAggregateState as a generic parameter, reflecting the new generic handler signature. The PersonAggregateState class was cleaned up to use standard F\# properties instead of mutable fields and the AllowNullLiteral attribute, and its event application logic was corrected to use the NewName field from the NameChanged event. Additionally, the PersonAggregate now captures the OldName when recording a name change, and the PersonConsumer was extended to handle the new SetPersonHeight command while adding ConfigureAwait(false) to existing async calls.

Test.Aggregates/Person · high confidence

Projection host builder now supports MongoDB alongside RavenDB

The \UseProjectionsWith\ extension method in the host builder has been refactored to accept generic type parameters for both the event repository and the projection store, enabling users to configure MongoDB as a persistence backend in addition to the existing RavenDB support. The implementation now branches based on the provided \ProjectionStore\ type (RavenDB or MongoDB), registering the appropriate client, database, and store services (such as \INoSqlStore\ and \ICheckpointStore\) for the selected backend, while also introducing a base \EventRepository\ class to standardize event repository inheritance.

SI.Rosetta.Projections.HostBuilder · high confidence

Projections subsystem refactored for MongoDB support and API simplification

The projection subsystem has been refactored to support MongoDB persistence and simplify its API. The checkpoint storage interface was consolidated from separate reader/writer interfaces into a single \ICheckpointStore\, and the \Projection\ class now uses this store instead of a dedicated writer. The \IProjectionsStore\ interface was updated to use generic \obj\ keys for load/delete operations and introduced a \LoadManyAsync\ method. Additionally, projection attributes were renamed (\SubscribedToStream\ to \HandlesStream\, \InactiveProjection\ to \DisabledProjection\) and the event type constraints were tightened to require \IAggregateEvents\ instead of the broader \IEvents\ interface.

SI.Rosetta.Projections · high confidence

RavenDB projection store API refactored and checkpoint logic unified

The RavenDB persistence layer in SI.Rosetta.Projections.RavenDB has been refactored to improve API consistency and async behavior. The RavenDbCheckpointWriter was removed and its functionality merged into a renamed RavenDbCheckpointStore, which now implements a unified ICheckpointStore interface for both reading and writing checkpoints. The RavenDbProjectionsStore interface was updated to use generic type constraints (non-struct) and accept object identifiers instead of strings, introducing a new LoadManyAsync method for bulk loading. Additionally, all asynchronous RavenDB client operations now explicitly use ConfigureAwait(false) to prevent potential deadlocks, and the retry delay for transient errors was increased from 50ms to 100ms.

SI.Rosetta.Projections.RavenDB · high confidence

Refactor EventStore client initialization and subscription constraints

The EventStore client initialization logic has been centralized into \SI.Rosetta.Persistence.EventStore\, replacing direct \EventStoreClientSettings\ usage in \ESCustomJSProjectionsFactory\ and \ESSubscriptionFactory\ with calls to \EventStoreFactory.InitializeProjectionManagementClient\ and \EventStoreFactory.InitializeEventStore\. Additionally, the \ESSubscription\ type and its factory now strictly require events to implement \IAggregateEvents\ instead of the broader \IEvents\ interface, narrowing the supported event types for subscriptions. The codebase also includes minor cleanup such as renaming modules to \CustomProjectionDiscovery\ and adding \.ConfigureAwait(false)\ to async calls.

SI.Rosetta.Projections.EventStore · high confidence

Refactored projection store type hierarchy

The projection store implementation has been restructured to consolidate base types. The specific RavenDB store type has been removed from its own file and merged into a shared ProjectionStores module, where both MongoDB and RavenDB now inherit from a common ProjectionStore base class.

SI.Rosetta.Projections.HostBuilder/ProjectionStores · high confidence

Refinement of Person domain models and test utilities

The Person domain model has been updated to distinguish between old and new values in the PersonNameChanged event, adding explicit OldName and NewName fields to improve clarity when tracking name changes. A new Reference type has been introduced in PersonMessages.fs to represent entities with an ID and name, while the UserReference type in Common.fs has been marked as CLIMutable to support serialization requirements. Additionally, the OrganizationMessages.fs module has been cleaned up by removing an unused System namespace import.

Test.PL · high confidence

Serialization interfaces updated to use AggregateEvents

The serialization module now targets the IAggregateEvents interface instead of the previous IEvents interface for both serializing and deserializing events. This change aligns the serialization logic with the updated aggregate event model, ensuring that event data is processed according to the new aggregate-specific structure.

SI.Rosetta.Serialization · high confidence

Simplified command and event interface hierarchy

The common message interfaces have been refactored to remove the previous inheritance structure. The specific \ICommands\ and \IEvents\ interfaces have been removed, and \IAggregateCommands\ and \IAggregateEvents\ are now standalone interfaces rather than inheriting from the generic command and event base types. \ICustomProjectionEvents\ now inherits directly from \IAggregateEvents\.

SI.Rosetta.Common · high confidence

Support for state-based aggregates alongside event sourcing

The host builder now allows applications to use state-based persistence (RavenDB) in addition to or instead of event sourcing. New extension methods \UseAggregatesWithEventSourcing\ and \UseAggregatesWithoutEventSourcing\ enable configuring either mode, while \UseAggregatesWith\ supports combining both. The previous single \UseAggregatesWith\ method has been replaced, and the repository hierarchy now distinguishes between \EventSourcedAggregateRepository\ and \StateBasedAggregateRepository\ implementations.

SI.Rosetta.Aggregates.HostBuilder · high confidence

Test.Aggregates sample updated to support mixed persistence and new organization aggregate

The Test.Aggregates sample application has been refactored to demonstrate the library's new capability to use Event Sourcing, non-event-sourced persistence, or a combination of both. The Program.fs now uses the generic \UseAggregatesWith\<EventStore, RavenDB\>\ method to configure this mixed persistence mode, replacing the previous single-store setup. Additionally, the sample now includes an \Organization\ aggregate alongside the existing \Person\ aggregate, with \ServiceInstance.fs\ updated to initialize and consume commands for both handlers, and the \AggregateConsumerBase\ renamed and updated to work with the new \IAggregateCommands\ interface.

Test.Aggregates · high confidence

Updated projection examples to use new stream handling and async patterns

The projection examples in Test.Projections/Projections have been updated to reflect API changes: the SubscribedToStream attribute is replaced by HandlesStream, and store operations (LoadAsync, StoreAsync) now require ConfigureAwait(false) for proper async handling. Additionally, stream names and projection types have been renamed (e.g., PersonStream to $ce-People, TotalPeopleCustomProjection to TotalPeopleAndOrganizationsCustomProjection) to better reflect their scope, and the TotalJohnsCustomProjectionHandler now tracks name changes for 'John' using NewName and OldName fields.

Test.Projections/Projections · high confidence

Test coverage

Added test domain models for Organization aggregate; Added unit tests for Organization aggregate behavior; Added unit tests for Organization projection and test infrastructure; Added unit tests for Organization projection handling.

Dependencies

Upgrade to .NET 9 and FSharp.Core 10.1 with dependency updates

The project has been upgraded to target .NET 9 and updated FSharp.Core to version 10.1.201/10.1.202. Several third-party dependencies have been updated, including Microsoft.Extensions.Hosting.Abstractions, Microsoft.Extensions.Configuration, Microsoft.Extensions.DependencyInjection, Newtonsoft.Json, EventStore.Client.Grpc, FSharp.Control.AsyncSeq, FSharp.Control.TaskSeq, System.Linq.Async, RavenDB.Client, and MongoDB.Driver. Additionally, the project now generates symbol packages (snupkg) for debugging support.

(dependencies) · high confidence

Housekeeping

Reordered import statements in Test.Projections host entry point

The order of open statements in the Test.Projections Program.fs file has been adjusted, moving the System.Reflection import above the SI.Rosetta.Projections.HostBuilder import. This is a minor code style or organization change with no impact on functionality.

Test.Projections · 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 60 → 55 (-4.8)
  • Rubric changed (rubric-2026.09.15 → rubric-2026.10.1) — scores are not directly comparable.

Lenses

  • Code Health 99 → 99 (+0.0)
  • Architecture 96 → 99 (+2.9)
  • Maturity 64 → 46 (-18.4)
  • Readiness 36 → 36 (+0.0)
  • Security 90 → 88 (-2.4)
  • Domain Modelling 100 → 100 (+0.0)

Resolved (3)

  • Documentation: no installation or build instructions (README.md)
  • Documentation: no licence statement (README.md)
  • Documentation: no usage examples (README.md)

New (17)

  • Documentation: no architecture or design documentation (README.md)
  • No test project references SI.Rosetta.Aggregates.EventStore (SI.Rosetta.Aggregates.EventStore/SI.Rosetta.Aggregates.EventStore.fsproj)
  • No test project references SI.Rosetta.Aggregates.HostBuilder (SI.Rosetta.Aggregates.HostBuilder/SI.Rosetta.Aggregates.HostBuilder.fsproj)
  • No test project references SI.Rosetta.Aggregates.RavenDB (SI.Rosetta.Aggregates.RavenDB/SI.Rosetta.Aggregates.RavenDB.fsproj)
  • No test project references SI.Rosetta.Aggregates.Template (SI.Rosetta.Aggregates.Template/SI.Rosetta.Aggregates.Template.fsproj)
  • No test project references SI.Rosetta.Persistence.EventStore (SI.Rosetta.Persistence.EventStore/SI.Rosetta.Persistence.EventStore.fsproj)
  • No test project references SI.Rosetta.Persistence.MongoDB (SI.Rosetta.Persistence.MongoDB/SI.Rosetta.Persistence.MongoDB.fsproj)
  • No test project references SI.Rosetta.Persistence.RavenDB (SI.Rosetta.Persistence.RavenDB/SI.Rosetta.Persistence.RavenDB.fsproj)
  • No test project references SI.Rosetta.Projections.EventStore (SI.Rosetta.Projections.EventStore/SI.Rosetta.Projections.EventStore.fsproj)
  • No test project references SI.Rosetta.Projections.HostBuilder (SI.Rosetta.Projections.HostBuilder/SI.Rosetta.Projections.HostBuilder.fsproj)
  • No test project references SI.Rosetta.Projections.MongoDB (SI.Rosetta.Projections.MongoDB/SI.Rosetta.Projections.MongoDB.fsproj)
  • No test project references SI.Rosetta.Projections.RavenDB (SI.Rosetta.Projections.RavenDB/SI.Rosetta.Projections.RavenDB.fsproj)
  • No test project references SI.Rosetta.Serialization (SI.Rosetta.Serialization/SI.Rosetta.Serialization.fsproj)
  • No test project references Test.Aggregates (Test.Aggregates/Test.Aggregates.fsproj)
  • No test project references Test.DTOs (Test.DTOs/Test.DTOs.csproj)
  • No test project references Test.PL (Test.PL/Test.PL.fsproj)
  • No test project references Test.Projections (Test.Projections/Test.Projections.fsproj)

Architecture

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

Removed bounded contexts (2)

  • SI.Rosetta.Persistence.MongoDB
  • SI.Rosetta.Persistence.RavenDB

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

Survey your own repository

si-informational-systems/Rosetta 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 3 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit f54e01c99bd5ecd6d3bd161db009e11be50d61c0 — the exact code this score is about.
  • Scored under rubric-2026.10.1 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-4f4226d619ea.