# `Wiztchta`
[🔗](https://github.com/darth-jorge/wiztcha/blob/v0.1.0/lib/wiztchta.ex#L1)

Drop-in, pluggable CAPTCHA for Phoenix forms and LiveViews.

Render a challenge inside any form with `Wiztchta.Components.wiztchta/1`
and check the submission with `verify/2` (or `Wiztchta.Plug` in controllers).

Wiztchta is stateless: each challenge travels to the browser as an
encrypted, expiring token that only your server can read. A pluggable
`Wiztchta.Store` rejects tokens that are submitted more than once.

## Configuration

    config :wiztchta,
      # Required: either a secret or an endpoint whose secret_key_base is used.
      endpoint: MyAppWeb.Endpoint,
      # secret_key_base: "...",

      # Optional (defaults shown):
      default_challenge: Wiztchta.Challenges.ProofOfWork,
      max_age: 300,
      store: Wiztchta.Store.ETS,
      param: "wiztchta"

Every option can also be passed per call to `new/1` and `verify/2`.

# `error`

```elixir
@type error() :: :missing | :invalid_token | :expired | :already_used | :wrong_answer
```

# `error_message`

```elixir
@spec error_message(error()) :: String.t()
```

A human-readable message for a `verify/2` error.

# `new`

```elixir
@spec new(keyword()) :: Wiztchta.Challenge.t()
```

Generates a new challenge.

## Options

  * `:type` - the `Wiztchta.Challenge` module to use. Defaults to the
    `:default_challenge` config.
  * `:max_age` - seconds until the challenge expires.
  * Any other option is forwarded to the challenge's `c:Wiztchta.Challenge.generate/1`
    (for example `difficulty: 18` for `Wiztchta.Challenges.ProofOfWork`).

# `valid?`

```elixir
@spec valid?(map(), keyword()) :: boolean()
```

Returns `true` if `verify/2` succeeds.

# `verify`

```elixir
@spec verify(map(), keyword()) :: :ok | {:error, error()}
```

Verifies a submitted challenge.

Accepts the full form params (looking under the `:param` key, `"wiztchta"`
by default) or the inner `%{"token" => ..., "response" => ...}` map.

A token is consumed on its first verification attempt, whether the answer
is right or wrong, so render a fresh challenge after every submit.

    case Wiztchta.verify(params) do
      :ok -> ...
      {:error, reason} -> ...
    end

---

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