Part of #166; RFC-0033 §8.6 level 2. Depends on the auth-spec issue (level 1).
Today token-based auth is one function: codex_refresh (RFC-0018 §3.2 leaves login, persistence and refresh orchestration to the integrator; the library raises AiMuxError::TokenExpired). Vertex has the same shape (GOOGLE_VERTEX_ACCESS_TOKEN, dies when the token expires) but no refresh path at all. There is no defined order for where a credential comes from.
Reference: pi-ai src/auth/resolve.ts (explicit key → env → credential store) and src/auth/credential-store.ts (in-memory default the integrator can replace). We adopt those two; we do not adopt pi-ai's src/auth/oauth/ login flows (device-code / PKCE for eight vendors) — RFC-0018's stance stands, because interactive login would have to be surfaced through seven language bindings. Recorded as an open question in RFC-0033 §8.6.
Work
Credential enum: ApiKey(String), BearerToken { token, expires_at: Option<_> }, Aws { access_key_id, secret, session_token, region }.
resolve_credential(spec: &AuthSpec, explicit: Option<Credential>, store: &dyn CredentialStore) -> Result<Credential> with the fixed order explicit → env → store, and a typed error naming the env var when nothing is found.
trait CredentialStore { get(provider) ; set(provider, credential) } with an in-memory default; exposed through the C ABI as one configure op (RFC-0033 §8.4 style), not per-language code.
- Generalise
codex_refresh into a TokenRefresher hook on bearer_token providers: on TokenExpired, call the refresher once, store the new token, retry the exchange once. Vertex gets a refresher that shells out nowhere — it simply surfaces TokenExpired unless the integrator installs one.
- Tests: resolution order; refresh-once-then-fail; store round trip through the C ABI op.
Part of #166; RFC-0033 §8.6 level 2. Depends on the auth-spec issue (level 1).
Today token-based auth is one function:
codex_refresh(RFC-0018 §3.2 leaves login, persistence and refresh orchestration to the integrator; the library raisesAiMuxError::TokenExpired). Vertex has the same shape (GOOGLE_VERTEX_ACCESS_TOKEN, dies when the token expires) but no refresh path at all. There is no defined order for where a credential comes from.Reference: pi-ai
src/auth/resolve.ts(explicit key → env → credential store) andsrc/auth/credential-store.ts(in-memory default the integrator can replace). We adopt those two; we do not adopt pi-ai'ssrc/auth/oauth/login flows (device-code / PKCE for eight vendors) — RFC-0018's stance stands, because interactive login would have to be surfaced through seven language bindings. Recorded as an open question in RFC-0033 §8.6.Work
Credentialenum:ApiKey(String),BearerToken { token, expires_at: Option<_> },Aws { access_key_id, secret, session_token, region }.resolve_credential(spec: &AuthSpec, explicit: Option<Credential>, store: &dyn CredentialStore) -> Result<Credential>with the fixed order explicit → env → store, and a typed error naming the env var when nothing is found.trait CredentialStore { get(provider) ; set(provider, credential) }with an in-memory default; exposed through the C ABI as oneconfigureop (RFC-0033 §8.4 style), not per-language code.codex_refreshinto aTokenRefresherhook onbearer_tokenproviders: onTokenExpired, call the refresher once, store the new token, retry the exchange once. Vertex gets a refresher that shells out nowhere — it simply surfacesTokenExpiredunless the integrator installs one.