Skip to content

Integrate with Chronicle

Cratis.Arc.Chronicle connects Arc’s command pipeline to Cratis Chronicle. Commands can return events for automatic appending, resolve projected state as dependencies, and use tenant context to select an event-store namespace. Arc continues to generate TypeScript clients from the command and query contracts.

Arc does not require Chronicle, and Chronicle does not require Arc. That independence is useful for adoption and bounded current-state slices. In a full Cratis information system, though, this integration is the natural pairing: Arc gives the CQRS boundary and Chronicle keeps the event-sourced facts underneath it.

The frameworks meet at one seam: an Arc command appends a Chronicle event, a Chronicle projection folds events into a read model, and an Arc query serves that read model back — with the generated TypeScript proxy carrying both ends to React.

command

returns an event

projection

query

React

[Command] record · Handle()

Chronicle event log

[ReadModel] · materialized to the sink

Reading that loop in code:

  • A command writes by returning. A [Command] record carries the command’s inputs as its properties, and the decision lives in a Handle() method on the record. Whatever Handle() returns is what Chronicle does with it — return an [EventType] event and it’s appended; the return signature (a single event, several, a tuple, a Result<,>, or nothing) decides the outcome. Returning events is the recommended path; transactional commands documents explicit append alternatives and their boundaries.
  • The event source id picks the stream. Every event belongs to one event source — one entity’s stream of history. Chronicle resolves that id from the command: a [Key] parameter, an EventSourceId or EventSourceId<T>-derived property, or ICanProvideEventSourceId. See Resolving EventSourceId.
  • The read model is projected, then queried. A [ReadModel] record declares the shape you want; [FromEvent<T>], [SetFrom<T>], and [SetValue<T>] map events onto its properties and Chronicle keeps it materialized in the configured sink (MongoDB by default). An Arc query — a static method on the read model, often returning an observable so the UI stays live — serves it through the generated proxy. See Read Models.
  • The loop closes: a command can read the state it helped build. When a decision depends on what’s already true, the command doesn’t query for it — Arc resolves the read model for the command’s key and hands it to the validator, Provide(), or Handle() as a parameter. See Use current state in a command.

So the round-trip is: a fact happens (command → event), it’s folded into state (projection → read model), and the UI reads it (query → proxy) — and the next command can read that same state to decide. Each piece is one of the topics below.

Without this package, Arc and Chronicle are independent. With it:

  • Commands return eventsHandle() methods on commands can return event records directly; the package appends them to the correct event log automatically.
  • Event source resolution — command input metadata selects the stream identity; authenticated identity and ordinary query binding are separate.
  • Read models backed by projections — Chronicle backing artifacts supply materialized or passive state. A materialized query can lag behind an append.
  • Tenant-aware event stores — each tenant’s event log and projections are namespaced automatically, matching Arc’s tenancy model.
  • Compliance integration — read-model interception requests PII release; append subjects come from command/event metadata, not automatically from authenticated identity. See the compliance reference for failure and passive-path limits.
  • Aggregate support — aggregate roots are discoverable and invocable via the standard command pipeline, with Chronicle managing the event stream and rehydration.
  • Current state as a command dependency — a command’s CommandValidator<>, Provide(), and Handle() can each take the read model Chronicle projected for the command’s key as an ordinary parameter, so a state-dependent decision needs no query round-trip.
TopicDescription
AggregatesWorking with aggregate roots and event sourcing.
Add event sourcing to an Arc sliceMove one database-backed slice to Chronicle while keeping its query and React screen in place.
Cratis PackageThe convenience package for Arc + Chronicle applications.
React to an eventRun side effects or follow-up commands from Chronicle events with reactors.
CommandsReturning events from commands, event source id resolution, and concurrency scoping.
Resolving EventSourceIdCommand identity selection, dependency timing, and the separate query-binding boundary.
Read ModelsWhat makes a read model injectable into a command, how it is resolved by key, and what happens when it does not exist.
TenancyTenant-aware namespaces for event stores and projections.
ValidationValidating a command against the state Chronicle already projected for its key.
CompliancePII decryption on read models and compliance subject resolution on commands.
Code AnalysisDiagnostics and analyzers specific to the Chronicle integration.