Skip to content
CAI
Software that uses CAICheck a score

EventSaucePHP/EventSauce

69.9

Adequate · 22 September 2026

5.7k

lines of production code

PHP

primary language

6

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is an event sourcing library that provides a modernized architecture for managing aggregate roots, message dispatching, and event consumption. It features a flexible serialization layer, automatic code generation for payloads, and support for snapshotting and message replay. The framework also includes an anti-corruption layer for message filtering and transformation, alongside comprehensive testing utilities for verifying aggregate behavior and message handling.

How it got here

2017–2018 — Event sourcing architecture modernization

12 changes.

This period focused on modernizing the event sourcing core by removing legacy components like the old repository and clock abstractions, while introducing a new message-based architecture with header-based metadata. The code generation system was refactored to support nullable types and user-defined interfaces, and the serialization layer was restructured to support flexible payload strategies and simplified upcasting.

2019–2021 — Snapshotting and test infrastructure

11 changes.

This period focused on introducing a snapshotting subsystem for aggregate roots, enabling state persistence and restoration. Concurrently, the codebase underwent significant refactoring of test utilities and message handling, including the addition of UUID decorators and the organization of test suites for event consumption and dispatching.

2022–2023 — Anti-corruption layer and testing infrastructure

9 changes.

This period focused on introducing an Anti-Corruption Layer for message filtering and translation, alongside a new message replay capability. The team also significantly expanded test coverage for aggregate roots and the new layer, while establishing a Pest-based testing utility suite to streamline test writing.

Features

Add Pest testing utilities for EventSauce

The src/PestUtilities directory now includes a new set of helper functions (given, when, then, expectToFail, etc.) that wrap the existing AggregateRootTestCase methods, allowing users to write more concise and readable tests using the Pest framework. A README file provides usage examples and installation instructions, while a .gitattributes file is added to manage file exports.

src/PestUtilities · high confidence

Add UUID message decorator with V4 and V7 generators

Introduced a new UuidMessageDecorator that automatically assigns a UUID to the EVENT\_ID header of each message. The component includes a UuidGenerator interface and two implementations: UuidV4Generator for standard random UUIDs and UuidV7Generator for time-sortable UUIDs. Tests verify that the decorator correctly applies the header and that each generator produces the expected UUID version.

src/UuidMessageDecorator · high confidence

Added message replay capability

Introduced a new \ReplayMessages\ class that enables replaying stored messages through a consumer, supporting pagination via a \PaginationCursor\. The implementation includes a \ReplayResult\ to track the number of messages handled and the next cursor state, along with \TriggerBeforeReplay\ and \TriggerAfterReplay\ interfaces to allow consumers to execute logic before and after the replay process.

src/ReplayingMessages · high confidence

Code generation now supports nullable types and user-defined interfaces

The code generation system has been refactored to support nullable field types and allow generated payload classes to implement user-defined interfaces. The \DefinitionGroup\ and \PayloadDefinition\ classes now track nullability and interface implementations, enabling the generated code to include \?\ type hints for nullable fields and \implements\ clauses for specified interfaces. Additionally, the \YamlDefinitionLoader\ has been updated to parse \nullable\ and \implements\ configurations from YAML definitions, and the \CodeDumper\ now generates the corresponding PHP code.

src/CodeGeneration · high confidence

Extracted test utilities into a dedicated module

Test helper classes, including the renamed MessageConsumerTestCase (formerly AggregateRootTestCase), AntiCorruptionLayerTestCase, and supporting classes like EventStager and ExpectedEvent, have been moved from the main EventSourcing package into a new TestUtilities module. This separation allows developers to require only the test utilities as a dev dependency, keeping the production package lean while providing a consistent API for testing message consumers and anti-corruption layers.

src/TestUtilities · high confidence

Introduce Anti-Corruption Layer for message filtering and translation

Added a new Anti-Corruption Layer that allows filtering and transforming messages before they are consumed or dispatched. The layer includes a \MessageFilter\ interface and implementations like \AllowAllMessages\, \NeverAllowMessages\, and \AllowMessagesWithPayloadOfType\ to control which messages pass through. It also provides a \MessageTranslator\ interface with a \MessageTranslatorChain\ for sequential transformations and a \MessageTranslatorPerPayloadType\ for type-specific translations. These components are wired into \AntiCorruptionMessageConsumer\, \AntiCorruptionMessageDispatcher\, and \AntiCorruptionMessageRelay\, enabling users to sanitize, validate, or adapt messages in a decoupled way.

src/AntiCorruptionLayer · high confidence

Introduce snapshotting support for aggregate roots

Added a new snapshotting subsystem that allows aggregate roots to persist and restore their state from snapshots. This includes a \Snapshot\ value object, a \SnapshotRepository\ interface, and an \InMemorySnapshotRepository\ for testing. The \AggregateRootWithSnapshotting\ interface and \AggregateRootRepositoryWithSnapshotting\ interface define the contract for snapshot-based retrieval and storage. A \ConstructingAggregateRootRepositoryWithSnapshotting\ class implements the logic to retrieve an aggregate from a snapshot and replay subsequent events, while the \SnapshottingBehaviour\ trait provides the core mechanism for creating and reconstituting from snapshots.

src/Snapshotting · high confidence

Introduced new message infrastructure and aggregate root abstractions

Added a new message-based architecture including the Message, MessageRepository, and MessageDispatcher interfaces and implementations. This introduces a header-based system for metadata (such as event type, time of recording, and aggregate root ID) via the Header constants. The AggregateRoot interface and AggregateRootBehaviour trait provide a modernized way to handle event sourcing, supporting both strict event application and known-event filtering. Additionally, a DefaultHeadersDecorator and ClassNameInflector system allow automatic header population and type mapping, while CollectingMessageDispatcher and CollectingMessageConsumer classes facilitate testing and message collection.

src · high confidence

New test utilities for aggregate root testing

A new \TestingAggregates\ module has been introduced under \src/TestUtilities/TestingAggregates\, providing a suite of test helpers for validating aggregate root behavior. This includes a \DummyAggregate\ and associated commands (e.g., \PerformDummyTask\, \InitiatorCommand\) and events (e.g., \AggregateWasInitiated\) that serve as a reference implementation for testing. The suite also includes a \DummyCommandHandler\ to route commands to the dummy aggregate, and an \ExampleAggregateRootTest\ that demonstrates how to use the \AggregateRootTestCase\ to verify event sequences, state transitions, and exception handling in a controlled environment.

src/TestUtilities/TestingAggregates · high confidence

Removals

Removed Time module (Clock, SystemClock, TestClock)

The Time module, including the Clock interface, SystemClock, TestClock, and their associated tests, has been removed from the codebase. This eliminates the ability to inject or mock time sources for event sourcing operations.

src/Time · high confidence

Removed code generation and fixtures from EventSourcing

The \CodeDumper\ class and associated test fixtures (including \definedWithYamlFixture.php\ and \groupWithVersionEventFixture.php\) have been deleted from the \src/EventSourcing/CodeGeneration\ directory. This removes the capability to automatically generate PHP code for events and commands, as well as the related documentation and sample files.

src/EventSourcing/CodeGeneration · high confidence

Removed core EventSourcing classes

The \AggregateRootRepository\, \Event\, \Message\, and \PointInTime\ classes have been removed from the \EventSourcing\ namespace. This eliminates the previous mechanism for persisting and retrieving aggregate roots via a message-based event store, along with the associated \PointInTime\ helper and its tests.

src/EventSourcing · high confidence

Behavioural changes

Migrate message decoration from metadata to headers

The test suite for message decoration has been moved to the LibraryConsumptionTests namespace and updated to use the new header-based API. Specifically, the test now expects the decorator to set headers rather than metadata, and assertions verify headers instead of metadata values. The test also uses the updated MessageDecoratorChain and EventStub classes.

src/LibraryConsumptionTests/DecoratingMessages · medium confidence

Migrated code generation fixtures to the new structure and updated generated classes to use \`SerializablePayload\`

The code generation fixtures have been reorganized from \src/EventSourcing/CodeGeneration/Fixtures\ to \src/CodeGeneration/Fixtures\. As part of this reorganization, the generated PHP classes (such as \definitionGroupWithDefaultsFixture.php\ and \simpleDefinitionGroupFixture.php\) have been updated to implement \SerializablePayload\ instead of the previous \Event\ or \Command\ interfaces. This change removes the requirement for \AggregateRootId\ and \PointInTime\ in the generated constructors and methods, simplifying the generated code by removing boilerplate related to event versioning and recording times. Additionally, new fixtures have been added to test features like interface implementation, field inheritance, and nullable types.

src/CodeGeneration/Fixtures · high confidence

Refactor event consumption to support type-based method inflection

The event consumption logic has been restructured into its own namespace, introducing a new \EventConsumer\ base class that delegates method resolution to pluggable inflectors. Two inflection strategies are now available: \InflectHandlerMethodsFromClassName\, which derives handler names from the event's class name, and \InflectHandlerMethodsFromType\, which inspects method signatures to match events by type. The type-based inflector specifically handles union types, allowing consumers to define handlers for multiple event types in a single method signature.

src/EventConsumption · high confidence

Refactored serialization architecture with new payload and message serializers

The serialization layer has been restructured to support flexible payload serialization strategies. A new \PayloadSerializer\ interface and \DefaultPayloadSerializer\ factory allow users to choose between \ObjectMapperPayloadSerializer\ (using reflection) and \ConstructingPayloadSerializer\ (using \SerializablePayload\ interface). The \MessageSerializer\ interface was updated to return a \Message\ object instead of a \Generator\ during unserialization, and the \ConstructingMessageSerializer\ was introduced to handle message serialization with header and payload separation. Additionally, a \MySQL8DateFormatting\ decorator was added to handle MySQL 8 date format compatibility, and a \TypeValidatingPayloadSerializer\ was introduced to enforce type constraints during serialization.

src/Serialization · high confidence

Removal of test and upcasting stubs from EventSourcing integration

The \src/EventSourcing/Integration\ area has had its test fixtures and upcasting stubs removed. Specifically, the \TestingAggregates\ namespace (including \DummyAggregate\, \DummyCommandHandler\, and related event classes) and the \Upcasting\ namespace (including \UpcastedEventStub\, \UpcasterStub\, and \UpcastingEventsTest\) have been deleted. This removes the dummy aggregate root implementations and the associated integration tests and upcasting utilities that were previously used for testing event sourcing behaviors.

src/EventSourcing/Integration · high confidence

Removed legacy serialization and upcasting components

The \ConstructingMessageSerializer\ and \EventType\ classes in the serialization namespace have been removed, along with the \DelegatableUpcaster\ interface and \DelegatingUpcaster\ implementation in the upcasting namespace. This eliminates the previous mechanism for serializing messages and delegating event upcasting, indicating a shift in how event data is persisted and transformed.

src/EventSourcing/Serialization, src/EventSourcing/Upcasting · high confidence

Simplified upcasting interface and serialization flow

The upcasting mechanism has been refactored to use a simpler, synchronous API. The \Upcaster\ interface no longer returns a \Generator\ or requires explicit type and version checks; instead, the \upcast\ method now takes and returns a plain \array\ message. This change is reflected in \UpcastingMessageSerializer\, which now directly calls the upcaster on the payload before passing it to the underlying serializer, removing the previous recursive or generator-based unserialization logic. Additionally, new helper classes \UpcasterChain\ and \UpcasterStub\ have been introduced to support chaining upcasters and testing, while \UpcastedPayloadStub\ serves as a test asset for serialization.

src/Upcasting · medium confidence

Updated PHPUnit configuration and added code quality tooling

The PHPUnit configuration was updated to version 9.3, which changes how code coverage is defined and excludes test, stub, and fixture files from the analysis. Additionally, new configuration files were added to support code quality and testing workflows: PHPStan for static analysis, PHP CS Fixer for code style, and a test runner script. The .gitattributes file was updated to exclude development and configuration files from package distributions, and the README was updated with build status and version badges.

(repo-wide) · high confidence

Test coverage

Add shopping cart example to consumption tests; Add test for aggregate root reconstitution failure; Add test for event handling; Added Pest-based test infrastructure and examples; Added snapshotting tests for the light switch aggregate; Added test suite for aggregate roots with delegated behavior; Added test utilities for message consumers; Added tests for Anti-Corruption Layer functionality; Added tests for synchronous message dispatching; Refactored test infrastructure for event consumption; Support for aggregates with custom constructors in base classes.

Dependencies

Updated project dependencies and tooling

The project dependencies have been updated to support PHP 8.0 and modernize the tooling ecosystem. The main package now requires psr/clock and eventsauce/clock, while dev dependencies have been upgraded to include phpstan, nikic/php-parser, and pestphp/pest alongside phpunit and symfony/yaml. Additionally, the docs site now uses an updated set of npm build dependencies including webpack 5.105.0, postcss 8.4.31, and tailwindcss 3.3.2.

(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

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 64 → 70 (+6.1)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 100 → 100 (+0.0)
  • Architecture 100 → 100 (+0.0)
  • Maturity 51 → 51 (+0.0)
  • Readiness 69 → 85 (+15.9)
  • Security 67 → 82 (+14.6)

Resolved (12)

  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • No exposed public API
  • Test reliability not included
  • The PestUtilities README is largely boilerplate code with no explanation of what it does or how to use the expectToFail, given, when, nothingShouldHaveHappened idioms. (PestUtilities/README.md)
  • The test-utilities README only states 'Code generation for EventSauce' and links to testing docs, with no explanation of what it generates or how tests are written. (TestUtilities/README.md)

New (16)

  • Dependency hygiene PARTLY measured — Composer dependencies read, no committed lock to grade for currency
  • Documentation: no installation or build instructions (README.md)
  • Documentation: no project overview (README.md)
  • Documentation: no usage examples (README.md)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Medium: security finding (details withheld)
  • Medium: security finding (details withheld)
  • Workflow holding a long-lived secret is unscoped

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

Survey your own repository

EventSaucePHP/EventSauce 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 22 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 33ea9b97ec3ac56991caad03b791fee418a43e41 — 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-821afab8930d.