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.json

Properties

FieldTypeRequiredDescription
type"event-type"YesDiscriminator.
idstringYesStable event type identifier, e.g. aws.cloudtrail. Pattern: ^[a-zA-Z][a-zA-Z0-9._-]*$
versionstringYesVersion label, e.g. v1 or 1. Min length: 1.
full_namestringNoHuman-readable name.
formatstringNoSerialisation format key: json (default), xml, kv, or line_kv.
xml_envelopeobjectNoRoot element name and attributes for format: xml. Only used when format is xml.
kv_layoutobjectNoSection/header layout for format: kv. Only used when format is kv, and required in that case. See kv_layout.
line_kv_layoutobjectNoSingle-line template/fields layout for format: line_kv. Only used when format is line_kv, and required in that case. See line_kv_layout.
schemaobjectYesJSON Schema for the event payload. See schema.
timestampstringNoPayload field stamped with the logical clock on every emit. Omit to disable clock stamping.
correlationstring[]YesDotted 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.
defaultsobjectNoDefault field values merged before scenario overrides. See defaults.
splunkobjectNoSplunk-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.

FieldTypeRequiredDescription
$schemastringYesJSON Schema dialect URI.
typestringYesRoot 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.

FieldTypeRequiredDescription
headerstring[]NoOrdered top-level field names rendered first, each on its own key=value line with no section header.
sectionsobject[]NoOrdered named field groups. Each renders as a <name>: line followed by tab-indented key=value members in field order.
sections[].namestringYesSection header text, rendered as <name>:. May contain spaces (e.g. Object Details).
sections[].fieldsstring[]YesOrdered field names rendered as tab-indented members of the section.
multivalue_separatorstringNoJoins array-valued fields (e.g. top|container|groupPolicyContainer). Default: |.

Rendering rules:

  • The payload is flat — every field named in header/sections is looked up directly in the event fields. A field that is a list is joined with multivalue_separator; a null value renders as key= (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=213594

line_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.

FieldTypeRequiredDescription
templatestringYesLiteral text prefix with {field} placeholders. Placeholder fields render value-only and are required on every event.
fieldsstring[]YesOrdered field names rendered as key<kv_separator>value pairs after the template, joined by pair_separator. Min 1, unique.
pair_separatorstringNoJoins successive key<kv_separator>value pairs. Default: ", ".
kv_separatorstringNoJoins each pair's key and value. Default: ": ".

Rendering rules:

  • The rendered line is the template with its {field} placeholders substituted, followed by the fields list rendered as ordered key<kv_separator>value pairs joined by pair_separator.
  • A fields entry absent from the event is omitted from the rendered line; the remaining pairs still join with pair_separator, so there is no dangling separator or empty pair.
  • Every event field must be declared in exactly one place — the template or fields — and every template placeholder must be present on the event. A field present in the event but declared nowhere is a hard error at emit time, as is a template placeholder missing from the event (the same undeclared-field discipline as kv_layout).
  • Values must be scalars. A value containing the pair_separator or 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: tcp

DstIP 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.com

splunk

Splunk-specific delivery identity for this surface, namespaced under splunk: so the otherwise vendor-neutral event-type schema doesn't read as Splunk-only.

FieldTypeDescription
sourcestring (ExprStr)Splunk source, e.g. XmlWinEventLog:${ref.System.Channel} (literal or per-emit interpolation).
sourcetypestring (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: XmlWinEventLog

pool.* 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:

PathStored key
eventIDeventID
System.EventRecordIDEventRecordID
System.ComputerComputer

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.Name and EventData.Name would both key as Name — 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: true

Events 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.