# `Attesto.PreAuthorizedCode`
[🔗](https://github.com/XukuLLC/attesto/blob/v2.0.1/lib/attesto/pre_authorized_code.ex#L1)

OID4VCI pre-authorized code issuance and redemption.

This module is pure logic over an `Attesto.PreAuthorizedCodeStore`.
`issue/3` binds the credential issuance context to a short-lived,
single-use code. `redeem/4` atomically consumes the code before checking
expiry or the optional transaction-code PIN and returns the grant context a
token endpoint uses to mint a credential access token.

The plaintext code is returned only from `issue/3`; the store receives its
hash. When a transaction code is bound, only its hash is stored as well.

# `grant`

```elixir
@type grant() :: %{
  subject: String.t(),
  credential_configuration_ids: [String.t(), ...],
  authorized_scopes: [String.t()]
}
```

# `issue_attrs`

```elixir
@type issue_attrs() :: %{
  :subject =&gt; String.t(),
  :credential_configuration_ids =&gt; [String.t(), ...],
  :authorized_scopes =&gt; [String.t()],
  optional(:tx_code) =&gt; String.t() | nil
}
```

# `issue`

```elixir
@spec issue(module(), issue_attrs(), keyword()) ::
  {:ok, String.t()} | {:error, :invalid_attrs}
```

Mint a short-lived, single-use pre-authorized code and persist it via `store`.

`attrs` must carry a non-empty `:subject`, a non-empty list of non-empty
`:credential_configuration_ids`, and an `:authorized_scopes` list. An
optional non-empty `:tx_code` is stored only as `:tx_code_hash`.

Options include `:ttl` (seconds, default `300`) and
`:now` (clock override). Returns `{:error, :invalid_attrs}` for malformed
issuance attributes.

# `redeem`

```elixir
@spec redeem(module(), String.t(), map(), keyword()) ::
  {:ok, grant()} | {:error, atom()}
```

Atomically consume and redeem a pre-authorized code.

The code is taken from the store before expiry or transaction-code
validation. A failed PIN check therefore burns the code. Returns a plain
grant-context map or an error atom.

---

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