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.jsonand auto-refreshed shortly before expiry.:api_key— anOPENAI_API_KEYfrom 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.
Summary
Functions
Return a valid access token / API key, refreshing the subscription if needed.
Whether a usable credential is present (no refresh attempted).
Returns a specification to start this module under a supervisor.
Preferred login entry: browser PKCE first, device-code when the callback port is
unavailable. callbacks is a map with
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.
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.
Forget the subscription credential (falls back to OPENAI_API_KEY if set).
HTTP headers the Provider should send (authorization + account id).
Install a credential (persists subscription credentials).
Human/diagnostic status of the current credential.
Types
@type credential() :: map()
Functions
@spec access_token(GenServer.server()) :: {:ok, String.t()} | {:error, map()}
Return a valid access token / API key, refreshing the subscription if needed.
@spec authenticated?(GenServer.server()) :: boolean()
Whether a usable credential is present (no refresh attempted).
Returns a specification to start this module under a supervisor.
See Supervisor.
@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— optionalfn message -> ... endwhen browser login is skipped
@spec login_browser(GenServer.server(), (map() -> 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.
@spec login_device_code(GenServer.server(), (map() -> 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.
@spec logout(GenServer.server()) :: :ok
Forget the subscription credential (falls back to OPENAI_API_KEY if set).
@spec request_headers(GenServer.server()) :: {:ok, [{String.t(), String.t()}]} | {:error, map()}
HTTP headers the Provider should send (authorization + account id).
@spec set_credential(GenServer.server(), credential()) :: :ok | {:error, map()}
Install a credential (persists subscription credentials).
@spec status(GenServer.server()) :: map()
Human/diagnostic status of the current credential.