Audit log¶
The optional Orchestra Audit Trail submodule (orchestra_audit_trail)
records every process transition into the
Audit Trail chain: a durable,
tamper-evident log that survives instance deletion. It complements the live
process trace; the trace shows the current run, the audit log is
the permanent record of who did what, and when.
How it works¶
The engine and the inbox dispatch a neutral OrchestraAuditableEvent at each
meaningful transition, with no knowledge of any backend. This submodule
subscribes to that event and writes each one into the Audit Trail chain. The
engine itself keeps zero dependency on audit_trail: enable the submodule
to turn the events into chain rows, or leave it off and consume the events
another way (an ECA model, a custom subscriber).
Enabling the submodule provisions a dedicated orchestra chain in
audit_trail (flag mode) that claims the orchestra channels. Flag mode keeps the
chain to the structured lifecycle events this module records, leaving out plain
engine log lines that happen to share the orchestra channel. Recording then
needs audit_trail to have a signing secret configured (see audit_trail's own
setup). A write that fails (for example before a secret exists) is logged on
the Orchestra channel and never breaks the running workflow, since the audit
log is an optional add-on.
Every row carries the instance UUID as its correlation id, so the audit trail groups all the rows of one process run together.
What it records¶
| Channel | Actions |
|---|---|
orchestra.instance |
started, completed, canceled, failed, incident_raised |
orchestra.task |
assigned, claimed, completed, reassigned, released, reoffered, canceled |
orchestra.token |
parked, resumed, canceled |
orchestra.variable |
set |
Every event can be toggled on the settings form. All of them are on by default
except variable set, which is off, as variable writes are high-volume. A
variable event records the variable name and scope (instance-wide or local to
one token branch); its value is dropped unless Also record the value is
turned on, since a value can hold arbitrary or personal data.
Permanent and transient context¶
Audit Trail keeps two context buckets per row: a permanent, HMAC-signed bucket, and a transient bucket that a retention policy can purge. The subscriber routes the structured, non-PII fields (workflow, node, tenant, outcome, reason, instance) to the permanent bucket, and leaves the actor and assignee user IDs in the transient bucket, so they stay GDPR-purgeable. A variable's name and scope are non-PII metadata and go to the permanent bucket; a recorded value stays transient, so it is purgeable along with the user IDs.
A task claimed or completed under a delegation carries an
extra on_behalf_of context key naming the person whose work it was. It is a
user ID, so it belongs with the actor in the transient, purgeable bucket.
Configuration¶
At Configuration > Workflow > Orchestra > Audit trail, toggle which
(channel, action) pairs are recorded. Every pair is on by default except
variable set. The setting is read at dispatch time, so a missing entry counts
as enabled and only an explicit off drops that event; that lets you silence a
noisy transition without touching code.
Alongside the variable Set toggle sits Also record the value, off by default. On, the value is serialized, length-capped and written to the transient bucket, which is what makes a forensic record of every data change possible. Off, only the name and scope are kept. It applies only while Set is enabled.
When a write fails¶
By default a chain-write failure is caught and logged on the orchestra
channel, and the workflow proceeds: a transition that happened is worth more
than a transition refused for want of a log row. Strict mode re-throws it
instead, for deployments where an auditable record is mandatory.
Strict mode does not by itself roll the transition back, and it is worth
knowing why before relying on it. Audit Trail stages a write made inside a
caller's transaction and chains it after that transaction commits, which is
what stops two writers taking the same head hash. So on its default write mode
the chain write happens when the transition is already committed, and a failure
there is retried by cron from the outbox rather than undoing anything: the
durability comes from the outbox, not from strict mode. Setting Audit Trail's
in-transaction write mode to inline restores the older behavior, where a
failing write aborts the caller's transaction, at the cost the staging exists to
avoid. And two of the transitions recorded here, a cancel and the completion
check, emit outside any transaction at all, so their fact is committed before
the write is attempted whichever mode is set.
Trace versus audit log¶
The trace and the audit log answer different questions. The trace is live observability: the token trail of a run, rebuilt from its retained tokens, and gone when the instance is deleted. The audit log is the durable record: an append-only, tamper-evident chain that outlives the instance, for compliance and forensics.
Requirements¶
orchestraaudit_trail