# `Pixir.Auth`
[🔗](https://github.com/Ranvier-Technologies/pixir/blob/main/lib/pixir/auth.ex#L1)

Owns the Session's **Credential** and serializes token refresh (ADR 0002).

A singleton GenServer (one per node). Two credential kinds reach the same Responses
Provider:

  * `:subscription` — a Codex OAuth token (primary), loaded from `~/.pixir/auth.json`
    and auto-refreshed shortly before expiry.
  * `:api_key` — an `OPENAI_API_KEY` from the environment (fallback). Never persisted.

Precedence: a stored subscription wins; otherwise `OPENAI_API_KEY` is used; otherwise
the Session is unauthenticated. Because all calls funnel through this one process,
refresh is naturally serialized — concurrent Turns never race to refresh.

The public API takes an optional `server` so tests can run an isolated instance with
an injected store path and OAuth module.

# `credential`

```elixir
@type credential() :: map()
```

# `access_token`

```elixir
@spec access_token(GenServer.server()) :: {:ok, String.t()} | {:error, map()}
```

Return a valid access token / API key, refreshing the subscription if needed.

# `authenticated?`

```elixir
@spec authenticated?(GenServer.server()) :: boolean()
```

Whether a usable credential is present (no refresh attempted).

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `login`

```elixir
@spec login(GenServer.server(), map(), keyword()) :: {:ok, map()} | {:error, map()}
```

Preferred login entry: browser PKCE first, device-code when the callback port is
unavailable. `callbacks` is a map with:

  * `:on_authorize` — `fn %{authorize_url, state} -> ... end`
  * `:on_device_code` — `fn %{user_code, verification_uri, interval, expires_in} -> ... end`
  * `:on_fallback` — optional `fn message -> ... end` when browser login is skipped

# `login_browser`

```elixir
@spec login_browser(GenServer.server(), (map() -&gt; any()), keyword()) ::
  {:ok, map()} | {:error, map()}
```

Run the browser PKCE login flow (ADR 0002). `on_authorize` is called with
`%{authorize_url, state}` so the caller can open the browser; this blocks the caller
(not the GenServer) while waiting for the localhost callback. On success the
credential is installed and `{:ok, status}` is returned.

# `login_device_code`

```elixir
@spec login_device_code(GenServer.server(), (map() -&gt; any()), keyword()) ::
  {:ok, map()} | {:error, map()}
```

Run the device-code login flow (ADR 0002). `on_user_code` is called with
`%{user_code, verification_uri, interval, expires_in}` so the caller can display the
code; this blocks the caller (not the GenServer) while polling. On success the
credential is installed and `{:ok, status}` is returned.

# `logout`

```elixir
@spec logout(GenServer.server()) :: :ok
```

Forget the subscription credential (falls back to `OPENAI_API_KEY` if set).

# `request_headers`

```elixir
@spec request_headers(GenServer.server()) ::
  {:ok, [{String.t(), String.t()}]} | {:error, map()}
```

HTTP headers the Provider should send (authorization + account id).

# `set_credential`

```elixir
@spec set_credential(GenServer.server(), credential()) :: :ok | {:error, map()}
```

Install a credential (persists subscription credentials).

# `start_link`

# `status`

```elixir
@spec status(GenServer.server()) :: map()
```

Human/diagnostic status of the current credential.

---

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