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, remote_child_orphaned, notice_undeliverable, notification_undeliverable |
orchestra.task |
assigned, claimed, completed, reassigned, released, reoffered, canceled |
orchestra.token |
parked, resumed, canceled, ignored |
orchestra.variables |
set |
Every event can be toggled on the settings form. All of them are on by default
except variables set, which is off, as variable writes are frequent. One
event records one write, however many variables it sets at once (a webform's
answers, a completion payload): the variable names and their scope
(instance-wide or local to one token branch). The values are dropped unless
Also record the values 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. Variable names and their scope are non-PII metadata and go to the permanent bucket; recorded values stay transient, so they are 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
variables 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 variables Set toggle sits Also record the values, off by default. On, each value is serialized, length-capped and written to the transient bucket, together with what the variables that already existed held before, so Audit Trail shows the write as the same diff as an entity update: which values changed and from what, and which variables are new. That is what makes a forensic record of every data change possible. Off, only the names 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¶
orchestra_engineaudit_trail