# `Chimeway.Policy`
[🔗](https://github.com/jonlunsford/chimeway/blob/v1.0.0/lib/chimeway/policy.ex#L1)

Dual-checkpoint policy engine for delivery suppression decisions.

Call `evaluate/2` at two points in the dispatch pipeline:

1. **Planning time** (before dispatch): pass `opts: []` — checks channel preference only.
2. **Perform time** (inside dispatcher, after delivery loaded): pass `check_read_state: delivery.delay_fallback`.

Returns:
- `{:ok, :proceed}` — delivery should proceed to the adapter.
- `{:suppress, reason_atom}` — delivery should be suppressed. `reason_atom` is a plain atom
  (`:channel_disabled`, `:already_read`). Persist as `Atom.to_string(reason_atom)` on the delivery row.

## Policy extensibility

A `policy_module` config key is reserved for custom host-app policy (quiet hours, rate limits):

    config :chimeway, :policy_module, MyApp.NotificationPolicy

This hook is not dispatched to in Phase 3 — it is the documented extension point for future phases.
Custom policy is additive; Chimeway's built-in preference and read-state checks always run first.

# `delivery_category`

```elixir
@spec delivery_category(Chimeway.Delivery.t()) :: String.t() | nil
```

# `evaluate`

```elixir
@spec evaluate(
  Chimeway.Delivery.t(),
  keyword()
) :: {:ok, :proceed} | {:suppress, atom()} | {:defer, map()}
```

Evaluates delivery policy and returns a proceed or suppress decision.

Options:
- `check_read_state:` (boolean, default false) — when true, checks if the associated
  in-app notification has been read (read_at is not nil). Used for delayed fallback paths.

---

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