mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-15 23:32:46 +00:00
fabro-auth defined its own `CredentialSource` trait beside the lithos `CredentialProvider`, with a parallel `ResolveError` and an adapter between them, because lithos had no way to ask which providers a store can serve right now. It does now: `credentials::readiness`, `ClientBuilder::build_ready`, and `CredentialError::Unusable`. - The vault, SQL vault, API-key, and extra-headers stores implement `CredentialProvider` directly. Material that is present but unusable (an expired token with no refresh, a wrong-typed vault entry, a header secret that did not resolve, a store read failure) is `CredentialError::Unusable` with the operator-facing reason; its `Display` replaces `auth_issue_message`. `is_configured` is the cheap presence check. - `fabro_llm::build_client` calls `build_ready`; `FabroClient::auth_issues` carries `CredentialError`. `fabro_llm::configured_providers` replaces the per-store `configured_providers` method. - `CredentialSource`, `ResolvedCredentials`, `lithos_credentials`, `ResolveError`, and `auth_issue_message` are deleted. Twenty files that held `Arc<dyn CredentialSource>` hold `Arc<dyn CredentialProvider>`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2.4 KiB
2.4 KiB
LLM Client Resolution
This document defines how Fabro resolves LLM credentials and constructs fabro-llm clients.
Core Rules
- The lithos
CredentialProvidertrait is the credential authority; Fabro's vault, SQL secret store, and API-key stores implement it directly. - Long-lived runtime contexts store
Arc<dyn CredentialProvider>andArc<Catalog>, notClient. - Call
fabro_llm::client::Client::from_source(&source, catalog).await?at the point of use. - Standalone setup and tests that use default settings build a default
Arc<Catalog>locally, then pass it explicitly. GenerateParams::new(model, client)always receives an explicitArc<Client>.- When a caller needs diagnostics in runtime request-serving paths, read
FabroClient::readyandauth_issues(fromClientBuilder::build_ready), or calllithos_llm::credentials::readinessdirectly. VaultCredentialSourceis the normal source for vault-backed runtime contexts;VaultCredentialSource::environment_only()serves env-only or no-vault contexts.
Why
- Rebuilding a client from the source at point of use preserves OAuth refresh behavior on long-running processes.
- Holding the source on contexts avoids process-global installs and cross-context leakage.
- Threading the catalog into credential resolution keeps custom providers, aliases, header-only providers, and API model IDs consistent across auth, client registration, and request translation.
- Requiring an explicit client on
GenerateParamsmakes the old silent fallback bug unrepresentable.
Application
- Workflow state lives on
RunServices.llm_sourceandRunServices.catalog. - Server state lives on
AppState.llm_sourceandAppState.catalog(). - Hooks and other long-lived executors receive a source plus catalog and derive clients when they actually generate.
- One-shot CLI commands may resolve a source locally, build a default settings catalog if they do not load runtime catalog settings, then derive a client once for that operation.
Enforcement
- Do not add new
Client::from_env-style shortcuts in production paths. - Do not cache a long-lived
Clientwhere OAuth refresh or storage-dir rebinding matters. - Do not construct LLM clients or resolve credentials without an explicit
Arc<Catalog>or&Catalog. - Mirror server-secrets-strategy.md: production credential resolution should be explicit about where secrets come from and how they flow into subprocesses.