# `Crank.Examples.Submission`
[🔗](https://github.com/code-of-kai/crank/blob/v0.2.0/lib/crank/examples.ex#L145)

A submission workflow where each state is its own struct.

`%Validating{}` has a `violations` field. `%Quoted{}` has `quotes`
and `selected`. `%Bound{}` has `quote` and `bound_at`. Each struct
carries only the fields that exist in that state. A `%Quoted{}`
can't have a `violations` field because the struct doesn't define
one. The compiler enforces this.

This is Scott Wlaschin's "Making Illegal States Unrepresentable"
pattern. It works in Crank without any special support because
`Machine.state` is `term()` -- structs are valid states.

    Validating ──validate──→ Quoted ──bind──→ Bound
        │                      │
        └──decline──→ Declined ←──decline──┘

State structs carry state-specific data. The `data` map carries
cross-cutting concerns shared across all states (parameters, audit).

When a field on the current state struct changes (adding a violation
to `%Validating{}`), the return is `{:next_state, %Validating{updated}, data}`.
The state value changed, so it's a state transition. `:keep_state`
is reserved for changes to `data` only.

Every event is handled in every state (total function).

## Type annotations

The `@type state` union below lists every valid state struct. Today
these annotations serve as documentation and Dialyzer input. When
Elixir's set-theoretic type system (introduced in v1.17) can check
them, unhandled state variants will produce compiler warnings
without any code changes.

# `data`

```elixir
@type data() :: %{parameters: map(), audit: [term()]}
```

Data shared across all states: parameters and an audit trail.

# `event`

```elixir
@type event() ::
  {:violation, atom()}
  | :validate
  | {:add_quote, map()}
  | {:select, non_neg_integer()}
  | :bind
  | :decline
  | :note
  | :noop
```

Events the submission machine accepts.

# `state`

```elixir
@type state() ::
  Crank.Examples.Submission.Validating.t()
  | Crank.Examples.Submission.Quoted.t()
  | Crank.Examples.Submission.Bound.t()
  | Crank.Examples.Submission.Declined.t()
```

One of the four state structs: `Validating`, `Quoted`, `Bound`, or `Declined`.

# `child_spec`

# `events`

```elixir
@spec events() :: [atom()]
```

Returns the list of atom events. Tuple events (`:violation`, `:add_quote`, `:select`) are generated separately in tests.

# `state_modules`

```elixir
@spec state_modules() :: [module()]
```

Returns the list of all state struct modules.

---

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