An AuditChange is one row mutation in one audited table.
An AuditChange records a single row-level mutation (INSERT, UPDATE,
or DELETE) on an audited table. Records are created automatically by
PostgreSQL triggers; you do not insert them from application code.
Each AuditChange belongs to exactly one AuditTransaction. Multiple
changes in the same database transaction share a transaction_id.
Key fields
:table_schema/:table_name— the schema and table where the mutation occurred.:table_pk— primary key of the mutated row, stored as a JSON map so composite keys are supported.:op—"INSERT","UPDATE", or"DELETE".:data_after— full row snapshot after the mutation (nil for deletes).:changed_fields— list of column names that changed (populated for updates; nil for inserts and deletes).:changed_from— sparse JSON map of prior column values on UPDATE when a per-table opt-in capture function is installed; otherwise nil.:captured_at— trigger execution timestamp (microsecond precision).
Stable 1.x fields
The stable struct fields for 1.x are id, transaction_id, table_schema,
table_name, table_pk, op, data_after, changed_fields,
changed_from, and captured_at. The t() type may gain fields; this list
does not make every current schema field or virtual relationship a promise.
data_after and changed_from are additive JSONB maps: keys and shapes may
be added in 1.x. changed_fields is an additive list of text column names.
These promises do not guarantee byte-stable JSON serialization or key order,
and existing rows are not rewritten when a shape grows.
Relationships
belongs_to :transaction, Threadline.Capture.AuditTransaction— the DB transaction that produced this change.
Setup
Triggers are installed per table by mix threadline.gen.triggers, which emits
SQL calling threadline_capture_changes() from mix threadline.install. See
guides/domain-reference.md for the domain model
for the capture
contract.
Summary
Types
@type t() :: %Threadline.Capture.AuditChange{ __meta__: Ecto.Schema.Metadata.t(), captured_at: DateTime.t(), changed_fields: [String.t()] | nil, changed_from: Threadline.json_map() | nil, data_after: Threadline.json_map() | nil, id: Ecto.UUID.t() | nil, op: String.t(), table_name: String.t(), table_pk: Threadline.json_map(), table_schema: String.t(), transaction: Threadline.Capture.AuditTransaction.t() | Ecto.Association.NotLoaded.t(), transaction_id: Ecto.UUID.t() | nil }
One persisted row mutation with its captured table, row key, operation, and JSON snapshots.
:data_after is nil for deletes, and :changed_fields is nil when no update fields were captured.