# `Ankusa.Verifier.Template`
[🔗](https://github.com/jamescarr/ankusa/blob/ankusa-v0.7.0/packages/ankusa/lib/ankusa/verifier/template.ex#L1)

The wire half of a signature scheme, shared by every verifier that reads a
signature out of a request header: `Ankusa.Verifier.Hmac` and
`Ankusa.Verifier.Asymmetric`.

A scheme is any struct with the fields `signature_header`, `parse`,
`sig_prefix`, `sig_key`, `version`, `signed` and `timestamp` (the
`Scheme` structs of both verifiers carry them). This module knows how to

  * pull the candidate signatures, and a signature-borne timestamp, out of
    the header (`candidates/2`),
  * read the timestamp and judge it against the replay window
    (`timestamp/4`), and
  * compile the `signed` template once (`compile/1`) and fill it per request
    with `{body}`, `{ts}` and `{header:NAME}` (`signed_iodata/3`).

What is *done* with those (an HMAC, an Ed25519 or RSA verification) is the
verifier's business. Every failure is a reason from the
`Ankusa.Verifier` vocabulary (`:missing_signature`, `:malformed_signature`,
`:timestamp_out_of_tolerance`).

# `compiled`

```elixir
@type compiled() :: [binary() | :body | :ts | {:header, String.t()}]
```

A `signed` template compiled by `compile/1`.

# `candidates`

```elixir
@spec candidates(Ankusa.Envelope.t(), struct()) ::
  {:ok, [String.t()], String.t() | nil}
  | {:error, :missing_signature | :malformed_signature}
```

The candidate signatures in `scheme.signature_header`, and the timestamp the
header itself carries (`{:sig, field}` schemes; `nil` otherwise).

# `compile`

```elixir
@spec compile(String.t()) :: compiled()
```

Compile a `signed` template once: a list of literal binaries, `:body`, `:ts`
and `{:header, lowercased_name}`. `signed_iodata/3` fills it per request
without copying the body.

# `signed_iodata`

```elixir
@spec signed_iodata(Ankusa.Envelope.t(), compiled(), String.t() | nil) ::
  {:ok, iodata()} | {:error, :missing_signature}
```

The bytes the provider signed, as iodata: a template compiled by `compile/1`
with `{body}`, `{ts}` and `{header:NAME}` filled in. The body is the
envelope's own binary, never copied. A header or `{ts}` the template names
but the request lacks is `:missing_signature`.

# `timestamp`

```elixir
@spec timestamp(Ankusa.Envelope.t(), struct(), String.t() | nil, keyword()) ::
  {:ok, String.t() | nil} | {:error, atom()}
```

The timestamp a scheme signs, checked against the replay window in `opts`
(`Ankusa.Verifier.check_timestamp/2`). `{:ok, nil}` for a scheme with no
timestamp. `sig_ts` is what `candidates/2` found in the signature header.

# `to_binary`

```elixir
@spec to_binary(iodata()) :: binary()
```

`signed_iodata/3`'s result as one binary, for a verifier whose primitive needs
the whole message more than once: a template that is the body alone comes
back as the body itself, any other costs one copy.

---

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