pub mod api;
pub mod cli;
use std::sync::Arc;
use anyhow::{Context, Result};
use bitrouter_cloud_sdk::BitrouterCloudAuthApplier;
use bitrouter_cloud_sdk::auth::credentials::{CredentialsStore, default_credentials_path};
use bitrouter_cloud_sdk::auth::metadata::AsMetadata;
use bitrouter_cloud_sdk::provider::PROVIDER_ID;
use bitrouter_observe::otel::TelemetryBearer;
use bitrouter_sdk::config::{Config, ProviderConfig};
use bitrouter_sdk::language_model::{AuthApplier, auth::AuthAppliers};
pub fn enable_in_zero_config(config: &mut Config) {
let Ok(path) = default_credentials_path() else {
return;
};
enable_in_zero_config_with_path(config, &path);
}
fn enable_in_zero_config_with_path(config: &mut Config, credentials_path: &std::path::Path) {
if config.providers.contains_key(PROVIDER_ID) {
return;
}
if !credentials_path.exists() {
return;
}
config.providers.insert(
PROVIDER_ID.to_string(),
ProviderConfig {
auto_discover: true,
..ProviderConfig::default()
},
);
}
pub fn build_auth_applier() -> Result<Arc<dyn AuthApplier>> {
let path = default_credentials_path().context("resolving BitRouter Cloud credentials path")?;
let applier =
BitrouterCloudAuthApplier::new(path).context("building the BitRouter Cloud AuthApplier")?;
Ok(Arc::new(applier))
}
pub fn register_if_configured(config: &Config, appliers: &mut AuthAppliers) -> Result<()> {
if !config.providers.contains_key(PROVIDER_ID) {
return Ok(());
}
let applier = build_auth_applier()?;
appliers.register(PROVIDER_ID, applier);
Ok(())
}
pub struct CloudBearer {
store: tokio::sync::Mutex<CredentialsStore>,
client: reqwest::Client,
metadata: Option<AsMetadata>,
}
impl std::fmt::Debug for CloudBearer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CloudBearer")
.field("store", &"<redacted>")
.field("metadata", &self.metadata)
.finish()
}
}
#[async_trait::async_trait]
impl TelemetryBearer for CloudBearer {
async fn bearer(&self) -> Option<String> {
let mut store = self.store.lock().await;
store
.current_token(&self.client, self.metadata.as_ref())
.await
.ok()
}
}
pub async fn cloud_bearer_source() -> Option<Arc<dyn TelemetryBearer>> {
let store = CredentialsStore::default_path().ok()?;
cloud_bearer_source_from_store(store).await
}
async fn cloud_bearer_source_from_store(
store: CredentialsStore,
) -> Option<Arc<dyn TelemetryBearer>> {
let credential = store.current()?;
let client = reqwest::Client::new();
let metadata = match credential.oauth() {
Some(creds) => Some(
bitrouter_cloud_sdk::auth::metadata::fetch(&client, &creds.authorization_server)
.await
.ok()?,
),
None => None,
};
Some(Arc::new(CloudBearer {
store: tokio::sync::Mutex::new(store),
client,
metadata,
}))
}
#[cfg(test)]
mod tests {
use super::*;
use bitrouter_cloud_sdk::auth::credentials::StoredCredential;
use std::fs;
use std::sync::atomic::{AtomicU64, Ordering};
fn fresh_tmp_creds_path(label: &str) -> std::path::PathBuf {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let id = COUNTER.fetch_add(1, Ordering::Relaxed);
let dir = std::env::temp_dir().join(format!(
"bitrouter-cloud-glue-{label}-{}-{id}",
std::process::id()
));
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).unwrap();
dir.join("account-credentials.json")
}
#[test]
fn enable_in_zero_config_noop_when_no_credentials_file() {
let path = fresh_tmp_creds_path("noop");
let mut config = Config::default();
enable_in_zero_config_with_path(&mut config, &path);
assert!(!config.providers.contains_key(PROVIDER_ID));
}
#[test]
fn enable_in_zero_config_inserts_when_credentials_file_present() {
let path = fresh_tmp_creds_path("inserts");
fs::write(&path, "{}").unwrap();
let mut config = Config::default();
enable_in_zero_config_with_path(&mut config, &path);
let provider = config
.providers
.get(PROVIDER_ID)
.expect("`bitrouter` provider should be auto-enabled when creds file is present");
assert!(
provider.auto_discover,
"auto_discover should be true so /models populates the routable list"
);
}
#[test]
fn enable_in_zero_config_noop_when_already_configured() {
let path = fresh_tmp_creds_path("already");
fs::write(&path, "{}").unwrap();
let mut config = Config::default();
config.providers.insert(
PROVIDER_ID.to_string(),
ProviderConfig {
api_base: "https://example.invalid".to_string(),
..ProviderConfig::default()
},
);
enable_in_zero_config_with_path(&mut config, &path);
assert_eq!(
config.providers.get(PROVIDER_ID).unwrap().api_base,
"https://example.invalid",
"existing entry must not be overwritten"
);
}
fn store_with_token(label: &str, access_token: &str, expires_at: &str) -> CredentialsStore {
let path = fresh_tmp_creds_path(label);
let json = serde_json::json!({
"access_token": access_token,
"expires_at": expires_at,
"token_type": "Bearer",
"scope": "telemetry:write",
"client_id": "bitrouter-cli",
"authorization_server": "https://api.bitrouter.ai",
});
fs::write(&path, serde_json::to_vec(&json).unwrap()).unwrap();
CredentialsStore::load(&path).unwrap()
}
#[tokio::test]
async fn cloud_bearer_source_none_when_not_signed_in() {
let path = fresh_tmp_creds_path("absent");
let store = CredentialsStore::load(&path).unwrap();
assert!(store.current().is_none(), "precondition: empty store");
assert!(
cloud_bearer_source_from_store(store).await.is_none(),
"an empty credential store must not build a live bearer source"
);
}
#[tokio::test]
async fn cloud_bearer_source_uses_stored_api_key_without_metadata() {
let path = fresh_tmp_creds_path("api-key-bearer");
let mut store = CredentialsStore::load(&path).unwrap();
store
.save(StoredCredential::api_key(
"brk_telemetry.secret".to_owned(),
"https://unreachable.invalid".to_owned(),
))
.unwrap();
let source = cloud_bearer_source_from_store(store).await.unwrap();
assert_eq!(
source.bearer().await.as_deref(),
Some("brk_telemetry.secret")
);
}
#[test]
fn cloud_bearer_debug_redacts_store() {
let store = store_with_token("dbg", "bra_secret", "2999-01-01T00:00:00Z");
let bearer = CloudBearer {
store: tokio::sync::Mutex::new(store),
client: reqwest::Client::new(),
metadata: Some(AsMetadata {
issuer: Some("https://api.bitrouter.ai".to_string()),
device_authorization_endpoint: "https://api.bitrouter.ai/device".to_string(),
token_endpoint: "https://api.bitrouter.ai/token".to_string(),
revocation_endpoint: None,
}),
};
let rendered = format!("{bearer:?}");
assert!(
!rendered.contains("bra_secret"),
"bearer token leaked in Debug: {rendered}"
);
assert!(rendered.contains("<redacted>"));
}
#[test]
fn malformed_credentials_file_is_swallowed_as_anonymous() {
let path = fresh_tmp_creds_path("malformed");
fs::write(&path, "{ not valid json").unwrap();
assert!(
CredentialsStore::load(&path).is_err(),
"a malformed credentials file must surface as a load error for \
`cloud_bearer_source` to swallow into anonymous"
);
}
}