# `Sake.Auth.DeviceGrant`
[🔗](https://github.com/hattoriai/sake/blob/v0.4.3/lib/sake/auth/records.ex#L93)

A device authorization grant (RFC 8628), stored hashed: `hash` is the
device code's, `user_code_hash` the user code's. `status` is
`:pending` until the person decides, then `:approved` (with
`subject_id` and the `scopes` they granted) or `:denied`, and
`:issued` once the client has its tokens. `last_polled_at` is when
the client last asked the token endpoint, against `interval`.

`extra` holds the device authorization request's parameters that are
not fields, as `Sake.Auth.PushedRequest`'s does: `"acr_values"` and
`"max_age"` (RFC 9470), with string keys and JSON values. `acr` and
`auth_time` are how and when the person who approved it signed in,
which its tokens carry.

# `status`

```elixir
@type status() :: :pending | :approved | :denied | :issued
```

# `t`

```elixir
@type t() :: %Sake.Auth.DeviceGrant{
  acr: term(),
  auth_time: term(),
  client_id: term(),
  expires_at: term(),
  extra: term(),
  hash: term(),
  inserted_at: term(),
  interval: term(),
  last_polled_at: term(),
  resource: term(),
  scopes: term(),
  status: term(),
  subject_id: term(),
  user_code_hash: term()
}
```

# `poll`

```elixir
@spec poll(t(), String.t(), DateTime.t()) ::
  {{:approved, t()}
   | :pending
   | :slow_down
   | :denied
   | :expired
   | :used
   | :error, t() | nil}
```

The answer to a poll of `grant` by `client_id` at `now`, and the grant
as it is after it (or nil when nothing changes), by the rules of
`c:Sake.Auth.Store.poll_device_grant/4`. A store calls it while it
holds the grant's row, and writes the grant back.

---

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