Skip to content
CAI
Software that uses CAICheck a score

disintegrate-es/disintegrate

64.7

Adequate · 21 September 2026

6.5k

lines of production code

Rust

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

Disintegrate is a Rust event-sourcing library that manages domain state by persisting immutable events to a PostgreSQL backend. It provides a decision-driven architecture where business logic validates commands against event streams before generating new events, supporting typed domain identifiers and configurable serialization formats like MessagePack. The system includes built-in capabilities for database schema migration, state snapshotting, and efficient event querying via indexed streams.

Features

Add banking example application

Introduces a new banking example application that demonstrates event-sourced account management. The example includes a Rust backend using the \disintegrate\ library for domain logic (account opening, closing, deposits, withdrawals, and transfers) and \actix-web\ for HTTP endpoints, backed by a PostgreSQL event store and snapshotter. It also provides a \.env\ configuration file for database connection and a \k6\ load test script to validate the system's behavior under concurrent load.

examples/banking · high confidence

PostgreSQL event store gains migration, snapshotting, and listener improvements

The PostgreSQL event store now includes a \Migrator\ component to handle schema initialization and version upgrades (such as migrating from v2.1.0 to v3.0.0 and v3.x.x to v4.0.0), and a new \PgSnapshotter\ for storing and retrieving state snapshots. The \PgEventStore\ constructor now supports automatic database initialization via \try\_new\, and the event listener has been refactored to support configurable retry actions, uninitialized database modes, and notification-based wake-ups for concurrent execution.

disintegrate-postgres/src · high confidence

Behavioural changes

Cart example adopts decision-based architecture with coupon support

The cart example has been refactored to use a decision-driven pattern where business logic is encapsulated in \AddItem\ and \ApplyCoupon\ decision structs rather than mutating the \Cart\ state directly. This introduces a new \Coupon\ aggregate and \CouponEvent\ stream, enabling users to apply coupons with validation (e.g., preventing double application or using out-of-stock coupons). The entry point now uses a \decision\_maker\ to process these decisions and persist events, replacing the previous manual hydration and mutation workflow.

examples/cart · high confidence

Courses example adopts Disintegrate v3.0.0 with PostgreSQL snapshotting and event-id-based read model consistency

The courses example has been upgraded to use the Disintegrate v3.0.0 architecture, replacing the previous generic state store with a PostgreSQL-backed decision maker that includes automatic snapshotting. This change removes the custom Postgres connection module in favor of the library's built-in snapshotter and decision maker, simplifying the application wiring. Additionally, the read model now tracks event IDs to ensure consistent updates, preventing race conditions during concurrent event processing. The example also integrates tracing for better observability and updates the gRPC reflection service to use the v1 API.

examples/courses/src · high confidence

Disintegrate v3.0.0 introduces decision-based architecture with multi-state support and typed identifiers

This release restructures the library around a new \Decision\ and \DecisionMaker\ pattern, allowing users to define business logic that validates against specific event streams before persisting changes. It replaces the previous \State\/\StateStore\ model with \EventSourcedStateStore\, \LoadState\, and \PersistDecision\ traits, adding support for multi-state queries and snapshotting. Domain identifiers are now strongly typed via \DomainId\ and \IdentifierValue\ (supporting String, i64, and Uuid), replacing the previous string-only \DomainIdentifier\. The event store API is generic over a configurable \EventId\ type (previously hardcoded to i64) and introduces \StreamItem\ for better stream handling, along with an \append\_without\_validation\ method for high-performance writes.

disintegrate/src · high confidence

Event store schema refactored to use sequences and advisory locks

The PostgreSQL event store schema has been restructured to improve performance and consistency. The \event\ table now uses a database sequence (\seq\_event\_event\_id\) for primary key generation instead of manual ID assignment, and the \event\_sequence\ table along with its associated GIN indexes on \domain\_identifiers\ have been removed. To support this new architecture, new SQL functions (\event\_store\_begin\_epoch\ and \event\_store\_current\_epoch\) were added to manage epoch boundaries using PostgreSQL advisory locks. Additionally, the index on \event\_type\ was changed from a HASH index to a BTREE index to optimize query performance.

_disintegrate-postgres/src/event\store/sql · high confidence

Introduce StateQuery derive and rename event groups to streams

Users can now derive the \StateQuery\ trait on structs to create typed queries against event streams, supporting optional renaming for snapshot identification and filtering by fields marked with the \\#\[id\]\ attribute. Additionally, the existing \\#\[group\]\ attribute on the \Event\ derive has been renamed to \\#\[stream\]\, and the underlying implementation now returns a \Result\ for better error handling. The macro also introduces a \SCHEMA\ constant on event types that exposes event names and domain identifier metadata, replacing the previous \NAMES\ constant.

disintegrate-macros · high confidence

Postgres listener refactors event handling and introduces ID indexing

The Postgres listener has been refactored to use a new event schema and identifier system, requiring users to update event definitions to use the new \EventSchema\ and \domain\_ids\ APIs instead of the previous \NAMES\ and \domain\_identifiers\ methods. The listener now requires an explicit \PgEventId\ type for event streams and uses \try\_new\ for event store initialization. Additionally, a new \PgIdIndexer\ component has been added to allow indexing existing fields tagged with \\#\[id\]\ in events, enabling queries on domain identifiers for historical events. The underlying database schema has also changed, removing the \event\_listener\_status\ table and trigger-based notifications in favor of a simpler \event\_listener\ table and polling-based execution.

disintegrate-postgres/src/listener · high confidence

Refactor domain models to use explicit Decision commands and immutable state

The domain models in the courses example have been refactored from a mutable state approach to an explicit command-driven architecture. State structs (Course, Student, Subscription, Unsubscription) now implement StateMutate and StateQuery traits, removing internal event history and relying on the framework for state reconstruction. Business logic has been moved out of the state structs into separate Decision structs (CreateCourse, CloseCourse, RenameCourse, RegisterStudent, SubscribeStudent, UnsubscribeStudent) which validate preconditions and emit events. This change makes the domain logic more testable and aligns with the updated disintegrate library's Decision-based workflow.

examples/courses/src/domain · high confidence

Refactored event store SQL generation and append logic

The event store's SQL construction has been rewritten to use parameterized queries for both appending and querying events. The previous \sql\_criteria\_builder.rs\ module, which generated SQL strings by interpolating values directly, has been removed and replaced with \append.rs\ and \query.rs\, which utilize \sqlx::QueryBuilder\ to safely bind event types, payloads, and domain identifiers. Additionally, the append method has been renamed to \append\_without\_validation\ to reflect the removal of concurrency checks during insertion.

_disintegrate-postgres/src/event\store · high confidence

Unified error handling and MessagePack serialization support

The library now provides a single, unified \Error\ type for all serialization and deserialization operations, replacing the previous format-specific error enums (such as \DecodeError\) in Avro, JSON, Prost, and Protobuf modules. This change simplifies error handling for users by standardizing how deserialization and conversion failures are reported. Additionally, a new MessagePack serializer and deserializer implementation has been added, allowing users to serialize and deserialize event data using the MessagePack format alongside the existing Avro, JSON, and Protobuf options.

disintegrate-serde · high confidence

Updated gRPC build tooling and concurrency test scope

The build process for the courses example now uses the \tonic\_prost\_build\ crate instead of \tonic\_build\ to generate gRPC code, reflecting a shift in the underlying build dependencies. Additionally, the example's test suite has been renamed from \subscriptions\_load\_test.js\ to \subscriptions\_concurrency\_test.js\ and its logic updated to simulate concurrent access across multiple courses and students, verifying error handling for scenarios like duplicate subscriptions and seat exhaustion.

examples/courses · high confidence

Test coverage

Removed event store integration tests

The integration tests for the PostgreSQL event store and state store implementations have been removed. This includes test cases for querying events, appending events with concurrency checks, and hydrating or saving state, which are no longer present in the \disintegrate-postgres/src/event\_store/tests\ directory.

_disintegrate-postgres/src/event\store/tests · high confidence

Dependencies

Disintegrate v4.0 release with MessagePack support and banking example

The Disintegrate event-sourcing library has been updated to version 4.0.0, introducing a new \serde-messagepack\ feature for MessagePack serialization alongside existing JSON, Protobuf, and Avro support. This major release upgrades core dependencies including \sqlx\ to 0.8.6, \tokio\ to 1.49.0, and \actix-web\ to 4.13.0, while also adding a new \examples/banking\ project to demonstrate the library's capabilities.

(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 62 → 65 (+2.4)
  • Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 100 → 99 (-0.9)
  • Architecture 100 → 99 (-0.6)
  • Maturity 75 → 71 (-3.6)
  • Readiness 49 → 49 (-0.7)
  • Security 58 → 71 (+12.9)
  • Domain Modelling 100 → 100 (+0.0)

Resolved (28)

  • Build action pinned to a mutable branch
  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • High vulnerability: [GHSA redacted] (Cargo.lock)
  • 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)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • LLM evaluation failed
  • Medium CVE: [GHSA redacted] (Cargo.lock)
  • Medium CVE: [GHSA redacted] (Cargo.lock)
  • …and 8 more

New (57)

  • Ambiguous naming overlap. matches takes a full PersistedEvent object, while matches_event takes a string (likely an event name/type). The naming convention is inconsistent (matches vs matches_event) and the distinction is not immediately obvious from the names alone (one might expect matches_event to take an event object).
  • Consistent pattern for safe/unsafe construction, but Identifier.is_valid_identifier(s: str): bool is redundant if new returns a Result. Callers can just try new and check the result. Exposing a separate validation method encourages a 'check-then-act' pattern which is less idiomatic than direct construction.
  • Duplicated block (10 lines × 2) (disintegrate-postgres/src/event_store.rs)
  • FunctionTooLong: disintegrate_macros::event::impl_enum (disintegrate-macros/src/event.rs)
  • High CVE: [GHSA redacted] (Cargo.lock)
  • 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)
  • 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)
  • …and 37 more

Changes since last survey

  • 2 commits — 2 feature/other, 0 fixes

By area

  • (root) — 2 commits

Notable commits

  • change: chore(deps): bump anyhow from 1.0.103 to 1.0.104 (#267)
  • change: chore(deps): bump tonic-health from 0.14.5 to 0.14.6 (#268)

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

Survey your own repository

disintegrate-es/disintegrate 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 33f12a0cd8a0650cfbd1f4336a58415b9bafa6b0 — 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.