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: datetimeRequired 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.causetentity_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 IDNote:
event.entity_idis a reserved field populated from the action’sentityIdparameter. It is always available as a fallback but using a named payload field (likeevent.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
| Type | Description | Example Value |
|---|---|---|
string | UTF-8 text | "artist-456" |
int | Integer | 42 |
number | Decimal (float/double) | 19.99 |
boolean | True or false | true |
datetime | ISO 8601 timestamp | "2024-06-15T20:00:00Z" |
array | Ordered list of values | ["a", "b"] |
object | Nested 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: stringOptional: kind
Events can be tagged with a kind to communicate their semantic role. This is informational — it does not change runtime behavior.
| Kind | Meaning |
|---|---|
event (default) | A normal domain fact |
system | An operational or infrastructure event |
fact | An external fact injected into the system |
compute | A derived or calculated event |
command | An event that acts as an intent (rare) |
events:
PROJECTION_FAILED:
state: _system
kind: system
entity_expr: event.entity_id
payload:
projection_name: string
error: stringReserved Field Names
The following field names are reserved and automatically populated by the event envelope. Do not declare them in payload:
| Field | Source |
|---|---|
type | Event type name (e.g. ARTIST_FOLLOWED) |
ts | Event timestamp (milliseconds since epoch) |
entity_id | Entity 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_UPDATEDReference in the root manifest:
# app.causet
includes:
events:
- ./events/**/*.events.causetNext steps
- Examples — concert-domain event catalog
- Best Practices — naming and payload mistakes
- Event Naming — conventions
- Dispatching Events — how rules emit events