# `MingaEditor.Frontend.FrameTransaction`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga_editor/frontend/frame_transaction.ex#L1)

Validates the render-frame boundary before a command batch reaches a frontend.

Semantic render commands must appear between matching `begin_frame` and `commit_frame` markers. Only a deliberately small set of setup and side-channel commands may be emitted outside a frame. The manager logs violations before it writes the batch so a producer regression is attributable without inspecting payload content.

# `frame_seq`

```elixir
@type frame_seq() :: non_neg_integer()
```

# `state`

```elixir
@type state() :: :outside | {:inside, frame_seq()}
```

# `validation_error`

```elixir
@type validation_error() ::
  {:malformed_command}
  | {:begin_while_open, frame_seq()}
  | {:commit_without_begin, frame_seq()}
  | {:commit_seq_mismatch, expected :: frame_seq(), received :: frame_seq()}
  | {:unterminated_frame, frame_seq()}
  | {:out_of_transaction_command, opcode :: non_neg_integer()}
```

# `format_error`

```elixir
@spec format_error(validation_error()) :: String.t()
```

Formats a validation error using only protocol metadata, never command payloads.

# `validate`

```elixir
@spec validate([binary()]) :: :ok | {:error, validation_error()}
```

Validates one ordered frontend command batch without inspecting payload data.

---

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