EventsDefining Events

Defining Events

Events are the facts that Causet records in the ledger. They are declared in .events.causet files and referenced by actions, projections, and sagas.


DSL Syntax

# events/concert.events.causet
events:
  ARTIST_FOLLOWED:
    state: user
    entity_expr: event.user_id
    payload:
      user_id:   string
      artist_id: string
 
  ARTIST_UNFOLLOWED:
    state: user
    entity_expr: event.user_id
    payload:
      user_id:   string
      artist_id: string
 
  SHOW_ANNOUNCED:
    state: artist
    entity_expr: event.artist_id
    payload:
      artist_id:    string
      show_id:      string
      venue:        string
      show_date:    datetime
      ticket_price: number
 
  TICKET_PURCHASED:
    state: user
    entity_expr: event.user_id
    payload:
      user_id:   string
      show_id:   string
      artist_id: string
      ticket_id: string
      price:     number
      purchased_at: datetime
 
  CONCERT_ATTENDED:
    state: user
    entity_expr: event.user_id
    payload:
      user_id:  string
      show_id:  string
      attended_at: datetime

Required Fields

state

The entity type (stream) this event belongs to. Must match a declared state in the DSL:

events:
  ARTIST_FOLLOWED:
    state: user   # must exist in states/*.state.causet

entity_expr

The expression that resolves the entity ID for this event. The entity ID determines which entity’s snapshot is updated when this event is emitted.

  • event.entity_id — use the reserved entity ID from the event envelope (always available)
  • event.<field> — use a specific payload field as the entity ID
events:
  ARTIST_FOLLOWED:
    entity_expr: event.user_id  # the "user_id" payload field is the entity ID

Note: event.entity_id is a reserved field populated from the action’s entityId parameter. It is always available as a fallback but using a named payload field (like event.user_id) is more explicit and self-documenting.

payload

The named fields carried by this event. These become available as event.<field> in projection derive expressions, side-effects rules, and listeners.


Payload Types

TypeDescriptionExample Value
stringUTF-8 text"artist-456"
intInteger42
numberDecimal (float/double)19.99
booleanTrue or falsetrue
datetimeISO 8601 timestamp"2024-06-15T20:00:00Z"
arrayOrdered list of values["a", "b"]
objectNested JSON object{ "key": "value" }

For typed arrays, use array<string>, array<int>, etc.:

payload:
  tag_ids:   array<string>
  scores:    array<number>

For typed objects, use nested YAML:

payload:
  address:
    street: string
    city:   string
    zip:    string

Optional: kind

Events can be tagged with a kind to communicate their semantic role. This is informational — it does not change runtime behavior.

KindMeaning
event (default)A normal domain fact
systemAn operational or infrastructure event
factAn external fact injected into the system
computeA derived or calculated event
commandAn event that acts as an intent (rare)
events:
  PROJECTION_FAILED:
    state: _system
    kind: system
    entity_expr: event.entity_id
    payload:
      projection_name: string
      error:           string

Reserved Field Names

The following field names are reserved and automatically populated by the event envelope. Do not declare them in payload:

FieldSource
typeEvent type name (e.g. ARTIST_FOLLOWED)
tsEvent timestamp (milliseconds since epoch)
entity_idEntity ID from the event envelope

Declaring any of these in your payload will cause a compiler error.


Organizing Events

Events can be split across multiple files. The compiler merges them. Use one file per domain:

events/
  concert.events.causet    # ARTIST_FOLLOWED, SHOW_ANNOUNCED, TICKET_PURCHASED
  venue.events.causet      # VENUE_CREATED, CAPACITY_UPDATED
  user.events.causet       # USER_REGISTERED, PROFILE_UPDATED

Reference in the root manifest:

# app.causet
includes:
  events:
    - ./events/**/*.events.causet

Next steps