Events and Dependencies
Events describe scenario behavior in CRADLE.
The events() block organizes events into three lifecycle phases:
events() >
preEvent(),
mainEvent(),
postEvent().
Each phase declares the events that belong to it. Every declared event is then defined in a matching event("name") block.
CRADLE events execute sequentially: one event completes before the next event begins. Use
dependsOn() to make required ordering between named events explicit.
Event lifecycle
CRADLE divides scenario behavior into three phases:
| Phase | Purpose |
|---|---|
preEvent() | Contains preparation that occurs before the primary scenario. |
mainEvent() | Contains the primary scenario behavior. |
postEvent() | Contains follow-up or evidence-related activity. |
The lifecycle can be viewed as:
Event properties
The current CRADLE reference documents the following event-related properties:
| Property | Arguments | Status | Description |
|---|---|---|---|
event | Semantic event name | Structural | Declares an event within a lifecycle phase. |
instance | Instance name | Schema required | Selects the instance associated with the event. |
needRoot | true or false | Schema required | Indicates whether elevated privileges are requested. CradleXC defaults to false. |
subject | Subject, parameters | Schema required | Identifies the execution subject and optional parameters. |
runObject | Object name, parameters | Schema required | Selects a declared object and optional parameters. |
pauseBeforeRun | Duration in seconds | Schema optional | Adds a delay before the event. CradleXC defaults to 0. |
pauseAfterRun | Duration in seconds | Schema optional | Adds a delay after the event. CradleXC defaults to 0. |
dependsOn | Event name | Schema optional | Adds an explicit dependency. Repeat for multiple dependencies. |
scheduleExecution | ISO 8601 date-time | Schema optional | Associates the event with a scheduled time. |
description | Text | Schema optional | Provides a human-readable description of the event. |
heuristic | Framework, identifier | Compiler extension | Associates an external classification or framework identifier with the event. |
Declare event phases
The lifecycle phases are declared through:
events() >
preEvent(),
mainEvent(),
postEvent().
Each phase can then declare its own events.
For example:
preEvent() >
event("initialize_client").
mainEvent() >
event("collect_evidence").
postEvent() >
event("cleanup").
This places:
- event
initialize_clientinpreEvent - event
collect_evidenceinmainEvent - event
cleanupinpostEvent
Each event must then have a corresponding definition.
Define an event
A named event block uses the form:
event("name") >
...
For example:
event("initialize_client") >
instance("Client"),
needRoot(false),
subject("bash", ""),
runObject("InitializationScript", ""),
pauseBeforeRun(0),
pauseAfterRun(0),
scheduleExecution("2026-01-15T10:00:00+00:00"),
description("Initialize the example client").
This event:
- runs on
Client - does not request root privileges
- uses
bash - runs the
InitializationScriptobject - has no delay before execution
- has no delay after execution
- does not wait for another event
- includes a scheduled execution time
- includes a description
Select an instance
Use instance() inside an event to identify the associated instance.
For example:
event("initialize_client") >
instance("Client").
The referenced instance should have been declared in instances():
instances() >
instance("Client").
and defined in a matching block:
instance("Client") >
os("ubuntu", "20.04").
Conceptually:
The instance name used by an event must match the corresponding declared instance.
Root privileges
Use needRoot() to indicate whether the event requests elevated privileges.
For example:
needRoot(false)
or:
needRoot(true)
needRoot() accepts a boolean value:
| Value | Meaning |
|---|---|
true | Request elevated privileges. |
false | Do not request elevated privileges. |
If needRoot() is omitted, CradleXC currently defaults to:
false
A typical event uses:
event("initialize_client") >
instance("Client"),
needRoot(false).
Execution subject
Use subject() to identify the execution subject and optional parameters.
For example:
subject("bash", "")
The first argument identifies the subject:
bash
The second argument contains optional parameters.
For example:
event("initialize_client") >
subject("bash", "").
The interpretation of the subject and its parameters depends on the scenario and supported CRADLE behavior.
Run an object
Use runObject() to select a declared object.
For example:
runObject("InitializationScript", "")
The first argument identifies the object:
InitializationScript
The second argument contains optional parameters.
The object should be declared in metadata:
metadata() >
object("InitializationScript").
and defined separately:
object("InitializationScript") >
location("${uriRemote}/scripts/initialize.sh").
The relationship is:
The object name passed to runObject() must match a declared object.
Object parameters
The second argument to runObject() can contain optional parameters.
For example:
runObject("InitializationScript", "")
uses no additional parameters.
Where parameters are required, use a structured map.
For example:
runObject("InitializationScript", {
mode = "safe",
count = 1
})
The exact interpretation of those values depends on the object and execution context.
Delay before an event
Use pauseBeforeRun() to add a delay before an event.
For example:
pauseBeforeRun(10)
The value represents a duration in seconds.
To request no delay:
pauseBeforeRun(0)
CradleXC currently defaults this property to:
0
when omitted.
Delay after an event
Use pauseAfterRun() to add a delay after an event.
For example:
pauseAfterRun(10)
To request no delay:
pauseAfterRun(0)
CradleXC currently defaults this property to:
0
when omitted.
Event dependencies
Use dependsOn() to express whether an event depends on another event.
For example:
dependsOn("initialize_client")
This makes the surrounding event wait for initialize_client. Omit the property when no explicit dependency is required.
For example:
mainEvent() >
event("initialize_client"),
event("collect_evidence").
event("initialize_client") >
instance("Client"),
needRoot(false),
subject("bash", ""),
runObject("InitializationScript", "").
event("collect_evidence") >
instance("Client"),
needRoot(false),
subject("bash", ""),
runObject("CollectEvidence", ""),
dependsOn("initialize_client").
Conceptually:
event("collect_evidence")event("initialize_client")Every dependsOn() value must match a defined semantic event name.
Event model
The scenario metadata selects the overall event model with eventType().
For example:
metadata() >
eventType("sequence").
The supported event type is:
sequence
Sequence
Use:
eventType("sequence")
for sequential event handling.
The Hello World example uses this event model.
Explicit dependencies
Use dependsOn() to describe ordering relationships between semantic event names while using the supported sequential event model.
Schedule an event
Use scheduleExecution() to associate an event with an ISO 8601 date-time.
For example:
scheduleExecution("2026-01-15T10:00:00+00:00")
A complete event can include:
event("initialize_client") >
instance("Client"),
scheduleExecution("2026-01-15T10:00:00+00:00").
Use a time-zone designator when specifying scheduled execution times.
The Hello World example contains:
scheduleExecution("2018-11-13T20:20:39+00:00")
for each lifecycle event.
Event descriptions
Use description() to explain the purpose of an event.
For example:
description("Initialize the example client")
Descriptions provide additional context when reading or reviewing a scenario.
For example:
event("initialize_client") >
instance("Client"),
description("Initialize the example client").
Event heuristics
Supported events can use:
heuristic("framework", "identifier")
For example:
event("initialize_client") >
heuristic("example-framework", "EXAMPLE-001").
Heuristic properties add classification metadata without replacing the event definition.
See Heuristics for documented conventions and examples.
Complete event example
The following example defines one event in the main phase:
events() >
preEvent(),
mainEvent(),
postEvent().
mainEvent() >
event("initialize_client").
event("initialize_client") >
instance("Client"),
needRoot(false),
subject("bash", ""),
runObject("InitializationScript", ""),
pauseBeforeRun(0),
pauseAfterRun(0),
scheduleExecution("2026-01-15T10:00:00+00:00"),
description("Initialize the example client").
The lifecycle relationship is:
events()
↓
mainEvent()
↓
event("initialize_client")
↓
event definition
Multiple events in a phase
A phase can contain more than one event.
For example:
mainEvent() >
event("initialize_client"),
event("collect_evidence"),
event("cleanup").
Each event should then have its own definition:
event("initialize_client") >
...
event("collect_evidence") >
...
event("cleanup") >
...
Semantic event names should be unique within the scenario.
Events across multiple phases
A scenario can define events across all three lifecycle phases.
For example:
events() >
preEvent(),
mainEvent(),
postEvent().
preEvent() >
event("initialize_client").
mainEvent() >
event("collect_evidence").
postEvent() >
event("cleanup").
This gives the scenario a clear lifecycle:
initialize_client
preEvent
↓
collect_evidence
mainEvent
↓
cleanup
postEvent
The canonical HelloWorld scenario declares all three phases and currently places one event in the main phase.
Hello World events
The Hello World scenario declares:
events() >
preEvent(),
mainEvent(),
postEvent().
The main phase contains:
mainEvent() >
event("initialize_client").
The event definition:
event("initialize_client") >
instance("router"),
needRoot(true),
pauseBeforeRun(0),
pauseAfterRun(0),
scheduleExecution("2018-11-13T20:20:39+00:00"),
description("HelloWorld Event").
This event:
- references
instance("router") - requests root privileges
- uses zero-second pauses
- does not wait for another event
- records an explicit execution timestamp
Cross-references
Events frequently connect several parts of a CRADLE scenario.
Consider:
event("initialize_client") >
instance("Client"),
runObject("InitializationScript", "").
This references:
Client
and:
InitializationScript
Those names should resolve to:
instances() >
instance("Client").
and:
metadata() >
object("InitializationScript").
Conceptually:
Schema and compiler behavior
The current schema and CradleXC behavior contain several event-related differences.
| Property | Current behavior |
|---|---|
instance | Required by the current schema. |
needRoot | Required by the schema, while CradleXC currently defaults to false. |
subject | Required by the current schema. |
runObject | Required by the current schema. |
pauseBeforeRun | Optional in the schema. CradleXC defaults to 0. |
pauseAfterRun | Optional in the schema. CradleXC defaults to 0. |
waitfor | The current schema and compiler behavior differ in how dependencies are represented. |
scheduleExecution | Optional in the current schema. |
description | Optional in the current schema. |
heuristic | Recognized by CradleXC as a compiler extension. |
The grammar, schema and compiler should not be treated as identical validation layers. Validate event behavior against the CradleXC release you are using.
Validate event definitions
Validate a scenario with:
cxc validate -i <scenario.cradle>
For example:
cxc validate -i scenarios/HelloWorld.cradle
When reviewing an event-related problem, check:
- whether the event belongs to a lifecycle phase
- whether the event has a matching
event("name")definition - whether the referenced instance exists
- whether the referenced object exists
- whether event names are unique
- whether
dependsOn()references resolve correctly - whether scheduled execution values use the intended date-time form
- whether compiler extensions are supported by the CradleXC release being used
Common mistakes
Event is declared but not defined
If a phase contains:
mainEvent() >
event("initialize_client").
there should be a corresponding:
event("initialize_client") >
...
Event definition does not belong to a phase
An event definition alone does not show which lifecycle phase contains it.
For example:
event("initialize_client") >
instance("Client").
should also be referenced by a phase:
mainEvent() >
event("initialize_client").
Event references an undeclared instance
Incorrect:
event("initialize_client") >
instance("Client").
when Client has not been declared.
Declare it through:
instances() >
instance("Client").
Event references an undeclared object
Incorrect:
event("initialize_client") >
runObject("InitializationScript", "").
without a corresponding object declaration.
Declare it in metadata:
metadata() >
object("InitializationScript").
and define it:
object("InitializationScript") >
location("${uriRemote}/scripts/initialize.sh").
Dependency references the wrong event name
If the intended dependency is event initialize_client:
dependsOn("initialize_client")
the scenario should contain a corresponding event named:
event("initialize_client")
Use matching event identifiers consistently.
Related documentation
- Syntax and Types
- Metadata
- Instances and Roles
- Objects and Interpolation
- Heuristics
- First Scenario
- Deployment IR
Next steps
Continue with Objects and Interpolation to learn how CRADLE declares external artifacts and constructs their locations.