Audit
Every important workflow action records an append-only
:class:~workflow_kit.models.WorkflowEvent. The audit trail is the single
source of truth for workflow activity; the
timeline subsystem derives its output from it.
What gets recorded
Each event captures:
execution— the workflow execution the event belongs to,event_type— a stable code (workflow_started,transition_executed,approval_required,approval_approved,approval_rejected,workflow_completed,workflow_cancelled),action— the transition/action name,source_state/target_state,user— the acting user (anonymous and system actions record no user),reason— free-form explanation (e.g. a rejection reason),metadata— optional JSON structured data (e.g.{"approval": <id>}),created_at— the timestamp.
Reading the trail
events = execution.history() # ordered by created_at, then id
event = events[0]
event.event_type # "workflow_started"
event.created_at
event.user # User or None
latest_event(execution) returns the most recent event, if any.
Append-only guarantee
WorkflowEvent.save() refuses to update an existing row: once persisted, an
event cannot be modified through the public API. Any attempt raises
AuditError, so historical truth is preserved.
Recording custom events
The audit service is also the API for appending events:
from workflow_kit.audit.service import record_event
from workflow_kit.models.history import WorkflowEventType
record_event(
execution,
event_type=WorkflowEventType.APPROVAL_APPROVED,
action="signed",
source_state="draft",
target_state="approved",
user=user,
reason="looks fine",
metadata={"approval": 42},
)