Automation Run Audit Trail
May 7, 2026 · View on GitHub
Overview
Workbench persists a durable audit trail for non-human-driven automation. This currently includes the new migration workflow and is intended to support scheduler backfills and future repair tasks.
Two MongoDB collections are used:
automationRuns: one summary row per automation executionautomationRunItems: per-item detail linked to a parent run byrun_id
These collections are operational diagnostics and audit records. They do not replace the version history stored on ATT&CK objects themselves.
When these collections are created
The collections are created lazily the first time an automation uses the recorder. The recorder also creates indexes needed for common queries.
As of now, the first built-in consumer is the
20260507130000-normalize-x-mitre-platforms migration.
What to expect in automationRuns
Each run document includes:
run_id: unique identifier for the executionautomation_type: coarse class such asmigrationname: specific job namestatus:running,completed,partial, orfailedstarted_atandfinished_atscope: what the job intended to operate oncounts: numeric counters from the jobwarnings: warning counters from the jobverification: post-run checkssummary: human-readable outcomeerror_summary: terminal failure detail, if any
What to expect in automationRunItems
Each item document includes:
run_id: parent run identifiersequence: item ordering within the runstatus: per-item result such aschanged,unchanged, orfailedaction: operation-specific verbtarget: identity envelope for the processed unitwarnings: optional warning codesdetails: automation-specific payload such as before/after valueserror: serialized failure detail when the item failed
Not every automation will use exactly the same details payload. That
field is intentionally extensible.
Common operator workflows
Inspect the latest automation runs
db.automationRuns.find().sort({ started_at: -1 }).limit(10).pretty()
Inspect the latest platform-normalization migration run
db.automationRuns.find(
{ name: '20260507130000-normalize-x-mitre-platforms' }
).sort({ started_at: -1 }).limit(1).pretty()
Fetch all item records for a run
const run = db.automationRuns.findOne(
{ name: '20260507130000-normalize-x-mitre-platforms' },
{ sort: { started_at: -1 } }
);
db.automationRunItems.find({ run_id: run.run_id }).sort({ sequence: 1 }).pretty();
Inspect failures only
db.automationRunItems.find({
run_id: run.run_id,
status: 'failed'
}).sort({ sequence: 1 }).pretty();
Inspect all runs that touched a specific STIX object
db.automationRunItems.find({
'target.stix_id': 'attack-pattern--01234567-89ab-cdef-0123-456789abcdef'
}).sort({ recorded_at: -1 }).pretty();
Interpreting run status
running: the automation started but has not recorded terminal state yetcompleted: the automation finished without item failurespartial: the automation made some progress but also encountered one or more failuresfailed: the automation did not complete successfully and did not produce a usable result set
The exact threshold between partial and failed is determined by
the automation implementation. Always inspect counts,
verification, and error_summary before deciding whether manual
intervention is required.
Interpreting verification
verification contains post-run checks claimed by the automation.
For example, the platform-normalization migration records
remaining_latest_active_objects_with_legacy_platforms.
This is the fastest way to answer, “Did the automation actually finish the intended repair?”
Logs vs persisted records
Container logs remain useful for real-time observation, but they are not the system of record. The durable record is MongoDB:
- logs are best for live troubleshooting
automationRunsandautomationRunItemsare best for audit and post-hoc analysis
When an automation emits a run_id in the logs, use that run_id to
retrieve the persisted record in MongoDB.
Retention and growth
There is currently no TTL or automatic pruning for these collections. That is intentional: operators may want to retain a complete history of database repairs and other automation.
If you later decide to prune:
- confirm any local retention or audit requirements
- prune old
automationRunItemsonly alongside their parentautomationRuns - never confuse these records with the authoritative STIX object
history stored in
attackObjectsandrelationships
Relationship to migration startup
If automatic migrations are enabled, migrations run on server startup.
See Configuration for the
database.migration.enable setting.
The automation audit trail is especially useful in environments where migrations run automatically, because it provides durable visibility into what happened after startup rather than relying only on container logs.