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

OID4VCI Credential Offer (`draft-ietf-oauth-openid4vci` §4.1).

Build the string-keyed Credential Offer object and its by-value or
by-reference `openid-credential-offer://` deep-link forms. This module is
pure and conn-free; fetching a referenced offer is the wallet's concern.

# `build`

```elixir
@spec build(keyword()) :: %{required(String.t()) =&gt; term()}
```

Build an OID4VCI Credential Offer object.

The required `:credential_issuer` and `:credential_configuration_ids`
options are validated and normalized into a JSON-ready map. When supplied,
`:grants` is normalized to the two OID4VCI grant types supported here:
`authorization_code` and `pre-authorized_code`.

# `deep_link`

```elixir
@spec deep_link(
  map(),
  keyword()
) :: String.t()
```

Build a by-value `openid-credential-offer://` deep link.

# `deep_link_by_reference`

```elixir
@spec deep_link_by_reference(
  String.t(),
  keyword()
) :: String.t()
```

Build a by-reference `openid-credential-offer://` deep link.

# `store_by_reference`

```elixir
@spec store_by_reference(module(), map(), keyword()) :: {:ok, String.t()}
```

Store `offer` for by-reference retrieval and return the freshly generated,
unguessable id to embed in its `credential_offer_uri`.

The id is the ONLY thing protecting a by-reference offer: the offer endpoint
is unauthenticated by design (OID4VCI §4.1.3, the wallet dereferences it
before it has any token), and a pre-authorized offer embeds a redeemable
`pre-authorized_code`. A guessable id therefore lets an attacker enumerate the
offer endpoint, read a victim's offer, and redeem its code first. This
function is the blessed creation path: it generates the id here with
`Attesto.Secret.generate/0` (256-bit CSPRNG), so a host cannot substitute a
weak one. It mirrors `Attesto.PresentationSession.create/3`, which owns its
session-id entropy the same way. Callers MUST use this rather than calling the
store's `put/1` with a self-chosen id.

Options:

  * `:ttl` — lifetime in seconds (default `300`).

Returns `{:ok, id}`; build the retrieval URL from `id` and pass that URL to
`deep_link_by_reference/2`.

# `to_query_value`

```elixir
@spec to_query_value(map()) :: String.t()
```

JSON-encode an offer for the `credential_offer` query parameter.

---

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