Event Type Schema
Complete field reference for event type definition files.
Complete field reference for event-type configuration files. For conceptual overview, see event types in scenario concepts.
IDE Integration
Add this directive to the top of your YAML file for autocomplete and validation:
# yaml-language-server: $schema=https://tracemill.dev/schemas/event-type.schema.jsonProperties
| Field | Type | Required | Description |
|---|---|---|---|
type | "event-type" | Yes | Discriminator. |
id | string | Yes | Stable event type identifier, e.g. aws.cloudtrail. Pattern: ^[a-zA-Z][a-zA-Z0-9._-]*$ |
version | string | Yes | Version label, e.g. v1 or 1. Min length: 1. |
full_name | string | No | Human-readable name. |
format | string | No | Serialisation format key: json (default), xml, kv, or line_kv. |
xml_envelope | object | No | Root element name and attributes for format: xml. Only used when format is xml. |
kv_layout | object | No | Section/header layout for format: kv. Only used when format is kv, and required in that case. See kv_layout. |
line_kv_layout | object | No | Single-line template/fields layout for format: line_kv. Only used when format is line_kv, and required in that case. See line_kv_layout. |
schema | object | Yes | JSON Schema for the event payload. See schema. |
timestamp | string | No | Payload field stamped with the logical clock on every emit. Omit to disable clock stamping. |
correlation | string[] | Yes | Dotted payload paths that together uniquely identify a generated event instance in the SIEM. The trailing segment of each path becomes the stored map key. See correlation. |
defaults | object | No | Default field values merged before scenario overrides. See defaults. |
splunk | object | No | Splunk-specific delivery identity (source, sourcetype), resolved per emit. See splunk. |
schema
A JSON Schema (draft 2020-12 recommended) describing the event payload structure. The engine validates every emitted event against this schema after merging defaults and scenario fields.
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | Yes | JSON Schema dialect URI. |
type | string | Yes | Root type, typically object. |
The schema can include required, properties, additionalProperties, and any other standard JSON Schema keywords.
kv_layout
Configures the section-headed, tab-indented key=value plain-text block emitted by the kv formatter (modeled on the Windows admon / Active Directory monitoring wire shape, sourcetype=ActiveDirectory). Because the event's fields are an unordered map, the layout is what supplies the wire order; it is required whenever format: kv.
| Field | Type | Required | Description |
|---|---|---|---|
header | string[] | No | Ordered top-level field names rendered first, each on its own key=value line with no section header. |
sections | object[] | No | Ordered named field groups. Each renders as a <name>: line followed by tab-indented key=value members in field order. |
sections[].name | string | Yes | Section header text, rendered as <name>:. May contain spaces (e.g. Object Details). |
sections[].fields | string[] | Yes | Ordered field names rendered as tab-indented members of the section. |
multivalue_separator | string | No | Joins array-valued fields (e.g. top|container|groupPolicyContainer). Default: |. |
Rendering rules:
- The payload is flat — every field named in
header/sectionsis looked up directly in the event fields. A field that is a list is joined withmultivalue_separator; anullvalue renders askey=(present but empty); there is no quoting or escaping. - A layout field absent from the event is skipped. A section whose members are all absent is omitted entirely, header included.
- A field present in the event but not declared anywhere in the layout is a hard error at emit time — the layout is the single source of field order, so an undeclared field has no defined position (this catches a field added to the scenario but forgotten in the layout, rather than silently dropping it).
- Field names may not contain a tab, newline, or
=; section names may not contain a tab or newline; each field name may appear in only one place (header or a single section).
format: kv
kv_layout:
header: [dcName, admonEventType]
sections:
- name: Names
fields: [objectCategory, displayName, distinguishedName]
- name: Object Details
fields: [objectGUID, objectClass]
- name: Event Details
fields: [uSNChanged, versionNumber]
multivalue_separator: "|"renders an event as:
dcName=ar-win-dc.example.local
admonEventType=Update
Names:
objectCategory=CN=Group-Policy-Container,CN=Schema,CN=Configuration,DC=example,DC=local
displayName=MSI
distinguishedName=CN={06F1A879},CN=Policies,CN=System,DC=example,DC=local
Object Details:
objectGUID=84f35cc2
objectClass=top|container|groupPolicyContainer
Event Details:
uSNChanged=213594line_kv_layout
Configures the single-line, template-prefixed key: value text emitted by the line_kv formatter (modeled on syslog-style vendor wire shapes, e.g. Cisco FTD). The layout supplies both the literal prefix and the field order for the pairs that follow it; it is required whenever format: line_kv.
| Field | Type | Required | Description |
|---|---|---|---|
template | string | Yes | Literal text prefix with {field} placeholders. Placeholder fields render value-only and are required on every event. |
fields | string[] | Yes | Ordered field names rendered as key<kv_separator>value pairs after the template, joined by pair_separator. Min 1, unique. |
pair_separator | string | No | Joins successive key<kv_separator>value pairs. Default: ", ". |
kv_separator | string | No | Joins each pair's key and value. Default: ": ". |
Rendering rules:
- The rendered line is the
templatewith its{field}placeholders substituted, followed by thefieldslist rendered as orderedkey<kv_separator>valuepairs joined bypair_separator. - A
fieldsentry absent from the event is omitted from the rendered line; the remaining pairs still join withpair_separator, so there is no dangling separator or empty pair. - Every event field must be declared in exactly one place — the
templateorfields— and everytemplateplaceholder must be present on the event. A field present in the event but declared nowhere is a hard error at emit time, as is atemplateplaceholder missing from the event (the same undeclared-field discipline askv_layout). - Values must be scalars. A value containing the
pair_separatoror a line break is rejected at emit time — either would forge extra pairs or records for a downstream line-oriented parser. There is no escape syntax, and keys are opaque strings (spaces allowed).
format: line_kv
line_kv_layout:
template: "{SyslogTime} {DeviceHostname} %FTD-{Severity}-{MessageID}: "
fields: [AccessControlRuleAction, SrcIP, DstIP, Protocol]given an event with SyslogTime=2026-08-19T10:00:00Z, DeviceHostname=firepower, Severity=1, MessageID=430002, AccessControlRuleAction=Block, SrcIP=10.1.2.3, Protocol=tcp, and DstIP absent, renders as:
2026-08-19T10:00:00Z firepower %FTD-1-430002: AccessControlRuleAction: Block, SrcIP: 10.1.2.3, Protocol: tcpDstIP is omitted from the line because it is absent from the event.
defaults
Default field values merged into every event of this type before scenario fields are applied. Scenario fields override defaults. ExprStr values (generators, refs) are supported.
Only top-level defaults: leaves are ExprStr; values nested inside an object or array default are emitted as literal text. (This is the inverse of state:, where nested leaves do evaluate.)
defaults:
eventVersion: "1.08"
eventTime: gen.timestamp()
eventSource: sts.amazonaws.comsplunk
Splunk-specific delivery identity for this surface, namespaced under splunk: so
the otherwise vendor-neutral event-type schema doesn't read as Splunk-only.
| Field | Type | Description |
|---|---|---|
source | string (ExprStr) | Splunk source, e.g. XmlWinEventLog:${ref.System.Channel} (literal or per-emit interpolation). |
sourcetype | string (ExprStr) | Splunk sourcetype, e.g. aws:cloudtrail. |
source and sourcetype are both intrinsic to the data — they describe what
Splunk parses the event as and where it came from, so they travel with each event.
This is what lets a single HEC pipeline carry every event type: the sink stamps the
per-event values on emit and falls back to the pipeline's static value only when the
event field is omitted. Only host and index remain destination concerns
configured on the pipeline, not the event surface.
The value is an ExprStr resolved per emit against the event's own merged fields, so it can be a literal or interpolate a payload field for per-event sub-typing:
# Literal — every event of this type shares one sourcetype
splunk:
sourcetype: aws:cloudtrail# Interpolated — sub-type per event from a payload field
splunk:
sourcetype: "o365:${ref.Workload}" # → o365:Exchange, o365:AzureActiveDirectory, …# Windows — source interpolated from the channel field, sourcetype fixed
splunk:
source: "XmlWinEventLog:${ref.System.Channel}"
sourcetype: XmlWinEventLogpool.* draws are rejected (they would materialize a fresh value on every event).
Only ${ref.*} interpolation against the event fields and the other non-pool
ExprStr forms are allowed.
correlation
Declares dotted payload paths that together uniquely identify a generated event instance in the SIEM. Required on every event type.
Each entry is a dotted path into the event payload. When the event is persisted, the engine walks nested maps using these paths to extract the value, and the trailing segment of the path becomes the stored map key:
| Path | Stored key |
|---|---|
eventID | eventID |
System.EventRecordID | EventRecordID |
System.Computer | Computer |
Pick paths whose trailing segment matches the field name your SIEM exposes after ingestion. The TA uses the stored map to search the SIEM, and the platform uses run_events.id (a stable UUID) as the reference key for reporting results back.
# Single field — native UUID
correlation: [eventID]
# Composite — network event without a native ID
correlation: [srcaddr, dstaddr, srcport, dstport, protocol]
# Nested — Windows/Sysmon events (stored keys: Computer, Channel, EventRecordID)
correlation: [System.Computer, System.Channel, System.EventRecordID]Constraints:
- The declared paths must resolve against the payload produced by the scenario. If any intermediate map is missing or any leaf is empty, the event's correlation map is null and the event is excluded from the validation manifest.
- No two paths may share the same trailing segment. The registry rejects event types where, for example,
System.NameandEventData.Namewould both key asName— pick paths with distinct leaves. - The declared paths must survive SIEM ingestion pipelines unchanged. Do not use
tracemill_*envelope fields — they may be stripped by some ingestion tools.
Example
type: event-type
id: aws.cloudtrail
version: v1
full_name: AWS CloudTrail Management Event
timestamp: eventTime
correlation: [eventID]
defaults:
eventVersion: "1.08"
eventTime: gen.timestamp()
schema:
$schema: https://json-schema.org/draft/2020-12/schema
type: object
required: [eventID, eventTime, eventSource, eventName]
properties:
eventID:
type: string
eventTime:
type: string
eventSource:
type: string
eventName:
type: string
additionalProperties: trueEvents are referenced in scenarios by id@version (e.g. aws.cloudtrail@v1) or bare id (resolves to the latest loaded version). The engine auto-discovers event types from event-types/ directories in the content hierarchy (project > user > library). An emit step that references an unknown event type is a hard error when event types are available.