Audit platform for Elixir teams using Phoenix, Ecto, and PostgreSQL.
Threadline combines trigger-backed row-change capture, rich action semantics (actor/intent/context), and operator-grade exploration.
Summary
Functions
Returns a keyset page of AuditTransaction records for a given actor, ordered by
occurred_at descending, then id descending.
Returns change rows across tables for one actor.
Returns one keyset page of change rows across tables for one actor.
Returns the row snapshot for a schema record at a point in time.
Returns every %Threadline.Capture.AuditChange{} for a single audit_transactions.id.
Projects a single %Threadline.Capture.AuditChange{} into deterministic, JSON-friendly maps.
Returns change rows linked to one correlation_id with strict correlation semantics.
Returns one keyset page of changes linked to one correlation_id.
Exports matching audit changes as CSV (same filters / opts as Threadline.Query.timeline/2).
Exports matching audit changes as JSON (same filters / opts as Threadline.Query.timeline/2).
Returns AuditChange records for a given schema record, ordered by
captured_at descending.
Returns one transaction-focused incident bundle with linked transaction/action context and packaged JSON-ready diffs.
Records a semantic audit action.
Returns the investigation slice for one schema row.
Returns one keyset page of row history for a single schema row.
Returns AuditChange records across tables, filtered by the given options,
ordered by captured_at descending, then id descending (same total order as
Threadline.Query.audit_changes_for_transaction/2; see Threadline.Query.timeline/2).
Returns one explicit keyset page of timeline results without changing timeline/2.
Returns one transaction-oriented investigation slice with linked transaction and optional action metadata.
Functions
Returns a keyset page of AuditTransaction records for a given actor, ordered by
occurred_at descending, then id descending.
Options
:repo— requiredEcto.Repomodule:limit— integer, maximum number of records to return (default 50):after— cursor to fetch older records:before— cursor to fetch newer records:from— inclusive lower bound onoccurred_at:to— inclusive upper bound onoccurred_at
Returns change rows across tables for one actor.
Returns one keyset page of change rows across tables for one actor.
Returns the row snapshot for a schema record at a point in time.
Options
:repo— requiredEcto.Repomodule
Returns every %Threadline.Capture.AuditChange{} for a single audit_transactions.id.
Delegates to Threadline.Query.audit_changes_for_transaction/2. Pass repo:
(required). Optional preload: (e.g. [:transaction]) is forwarded when
non-empty — see the Query function for ordering and UUID rules.
Projects a single %Threadline.Capture.AuditChange{} into deterministic, JSON-friendly maps.
Delegates to Threadline.ChangeDiff.from_audit_change/2. See that module for :format
(including :export_compat) and :expand_insert_fields.
Returns change rows linked to one correlation_id with strict correlation semantics.
Returns one keyset page of changes linked to one correlation_id.
Exports matching audit changes as CSV (same filters / opts as Threadline.Query.timeline/2).
Exports matching audit changes as JSON (same filters / opts as Threadline.Query.timeline/2).
Pass json_format: :ndjson in opts for newline-delimited objects. See Threadline.Export
and Threadline.Query.timeline/2.
Returns AuditChange records for a given schema record, ordered by
captured_at descending.
Structs include :changed_from when present in the row (sparse prior values on
UPDATE under an opt-in per-table capture function; nil when disabled or on
INSERT/DELETE rows).
Options
:repo— requiredEcto.Repomodule
Returns one transaction-focused incident bundle with linked transaction/action context and packaged JSON-ready diffs.
Returns {:ok, bundle} when the parent AuditTransaction exists, even if it
has no captured changes. Returns {:error, :not_found} when the transaction
row does not exist.
Records a semantic audit action.
Required options
:actoror:actor_ref—%ActorRef{}identifying who performed the action:repo— theEcto.Repomodule to use for insertion
Optional options
:status—:okor:error(default::ok):verb— string or atom (e.g.,"update"):category— string or atom (e.g.,"membership"):reason— atom (e.g.,:insufficient_permissions):comment— free-text string explanation:correlation_id— cross-boundary correlation ID string:request_id— request ID string (fromPlug.RequestId/x-request-id):job_id— Oban job ID string
Returns
{:ok, %AuditAction{}}on success{:error, %Ecto.Changeset{}}if changeset validation fails{:error, :missing_actor}if no actor was provided{:error, :invalid_actor_ref}if the actor fails ActorRef validation{:error, :missing_repo}if:repois not provided
Returns the investigation slice for one schema row.
This is the discoverable row-history helper for operators who want one row's changes without assembling table and primary-key predicates manually.
Returns one keyset page of row history for a single schema row.
Returns AuditChange records across tables, filtered by the given options,
ordered by captured_at descending, then id descending (same total order as
Threadline.Query.audit_changes_for_transaction/2; see Threadline.Query.timeline/2).
Use timeline/2 for eager, bounded slices where returning a full list is still
the simple path. Use timeline_page/2 for larger investigation windows where
stable keyset traversal matters.
Options
:table— string or atom; filters bytable_name:actor_ref—%ActorRef{}; filters by actor via a JOIN toaudit_transactions:from—DateTime; inclusive lower bound oncaptured_at:to—DateTime; inclusive upper bound oncaptured_at:correlation_id— non-empty binary; only changes whose transaction is linked to anaudit_actionsrow with that correlation id (strict semantics — seeThreadline.Query).:repo— requiredEcto.Repomodule
Returns one explicit keyset page of timeline results without changing timeline/2.
Uses the same filter vocabulary as timeline/2, but returns a page struct so
large investigation windows can be traversed incrementally while timeline/2
stays eager for existing callers. Paging controls live in opts:
:page_size— positive integer, defaults to1000:cursor—%{captured_at: %DateTime{}, id: uuid}from a prior page'snext_cursor:repo— requiredEcto.Repomodule
Returns one transaction-oriented investigation slice with linked transaction and optional action metadata.
This packages the existing transaction drill-down primitive into a reusable helper contract without adding Phase 55 diff or incident-bundle rendering.