# `Capstan.Change`
[🔗](https://github.com/baselabs/capstan/blob/v1.3.1/lib/capstan/change.ex#L1)

A single row change within a `Capstan.Transaction`.

`record` is the row AFTER the change — a `column_name => value` map — present
for `:insert`/`:update` and `nil` for `:delete`. `old_record` is the row BEFORE
the change, present for `:update`/`:delete` and `nil` for `:insert`.

`:snapshot` (C2) is a backfill row delivered by the initial-snapshot path, NOT a
streamed committed change: `record` is the full row, `old_record` is `nil`, and it
carries no GTID (a snapshot chunk is not a committed transaction — see
`c:Capstan.Sink.handle_snapshot/2`). It is delivered through `handle_snapshot/2`, never
`handle_transaction/1`.

Column VALUES are user data (Rule 1) — never logged or attached to telemetry.
Column NAMES stay strings, never atoms (a wide or attacker-influenced schema
must not exhaust the atom table).

# `t`

```elixir
@type t() :: %Capstan.Change{
  old_record: map() | nil,
  op: :insert | :update | :delete | :snapshot,
  record: map() | nil,
  schema: String.t(),
  table: String.t()
}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
