# `Arcanum.Auth.Copilot`
[🔗](https://github.com/kakilangit/arcanum/blob/v0.1.0/lib/arcanum/auth/copilot.ex#L1)

GitHub Copilot OAuth device code authentication.

Implements the OAuth 2.0 Device Authorization Grant (RFC 8628) to obtain
a GitHub access token that works directly against `api.githubcopilot.com`.

## Flow

    1. `start_device_flow/0`  → returns {verification_uri, user_code, device_code}
    2. User visits verification_uri and enters user_code
    3. `poll_for_token/1`     → polls GitHub until user authorizes
    4. The access_token is used directly as Bearer token against Copilot API

No secondary token exchange is needed — the GitHub OAuth token works as-is.

# `device_flow`

```elixir
@type device_flow() :: %{
  device_code: String.t(),
  user_code: String.t(),
  verification_uri: String.t(),
  interval: pos_integer()
}
```

# `base_url`

```elixir
@spec base_url(String.t() | nil) :: String.t()
```

Returns the Copilot API base URL.

# `copilot_headers`

```elixir
@spec copilot_headers(String.t()) :: [{String.t(), String.t()}]
```

Returns the headers required for Copilot API requests.

# `poll_for_token`

```elixir
@spec poll_for_token(device_flow(), String.t() | nil) ::
  {:ok, String.t()} | {:error, term()}
```

Polls GitHub for the access token after the user has entered the device code.

Blocks the calling process, polling every `interval + 3` seconds (per RFC 8628).
Returns `{:ok, access_token}` when the user authorizes, or `{:error, reason}` on failure.

Accepts an optional `enterprise_domain` for GitHub Enterprise.

# `poll_once`

```elixir
@spec poll_once(String.t(), String.t() | nil) ::
  {:ok, String.t()} | {:pending, atom()} | {:error, term()}
```

Makes a single poll request to GitHub's OAuth token endpoint.

Returns:
- `{:ok, access_token}` — user authorized, token obtained
- `{:pending, :authorization_pending}` — user hasn't authorized yet
- `{:pending, :slow_down}` — polling too fast, caller should increase interval
- `{:error, reason}` — terminal failure (expired, denied, network error)

Intended for external polling loops (e.g. Oban jobs) that manage their
own scheduling instead of blocking a process.

# `start_device_flow`

```elixir
@spec start_device_flow(String.t() | nil) :: {:ok, device_flow()} | {:error, term()}
```

Starts the OAuth device code flow.

Returns a map with `device_code`, `user_code`, `verification_uri`, and `interval`.
The caller should display `user_code` and `verification_uri` to the user,
then call `poll_for_token/1` with the returned map.

Accepts an optional `domain` for GitHub Enterprise (e.g. `"company.ghe.com"`).

---

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