use super::*;
use wiremock::{
matchers::{method, path},
Mock, MockServer, ResponseTemplate,
};
struct Environment(Vec<(&'static str, Option<std::ffi::OsString>)>);
impl Environment {
fn capture(names: &[&'static str]) -> Self {
Self(
names
.iter()
.map(|name| (*name, std::env::var_os(name)))
.collect(),
)
}
}
impl Drop for Environment {
fn drop(&mut self) {
for (name, value) in &self.0 {
unsafe {
match value {
Some(value) => std::env::set_var(name, value),
None => std::env::remove_var(name),
}
}
}
}
}
fn direct_row(endpoint: String, key: &str) -> ModelSchema {
let mut row = registry::builtin_catalog()
.into_iter()
.find(|s| s.id == "parslee/jev")
.unwrap();
row.id = "typesafe/test-direct".into();
row.provider = "typesafe".into();
row.name = "jev-latest".into();
row.tags.clear();
row.source = ModelSource::Proprietary {
provider: "typesafe".into(),
endpoint,
auth: schema::ProprietaryAuth::ApiKeyEnv {
env_var: key.into(),
},
protocol: schema::ProprietaryProtocol {
chat_path: "/v1/systemone".into(),
wire: ProprietaryWire::SystemOne,
..Default::default()
},
};
row
}
fn engine_at(root: &Path) -> InferenceEngine {
InferenceEngine::new(InferenceConfig {
state_root: root.to_path_buf(),
models_dir: root.join("models"),
..Default::default()
})
}
fn classify_request() -> ClassifyRequest {
ClassifyRequest {
text: "billing question".into(),
labels: vec!["billing".into(), "other".into()],
model: None,
work_context: None,
}
}
#[test]
fn typesafe_direct_configured_missing_key_does_not_select_parslee() {
let direct = direct_row("http://127.0.0.1:1".into(), "TYPESAFE_MISSING_TEST_KEY");
let mut parslee = registry::builtin_catalog()
.into_iter()
.find(|s| s.id == "parslee/jev")
.unwrap();
parslee.available = true;
assert_eq!(
default_system_one_classifier([&parslee, &direct].into_iter()).as_deref(),
Some("typesafe/test-direct")
);
}
#[tokio::test]
async fn typesafe_direct_traffic_and_audit_in_both_parslee_states() {
let _environment = openrouter::test_environment_scope_async().await;
let _home = openrouter::StateRootScope::new();
let root = tempfile::tempdir().unwrap();
let key_name = "TYPESAFE_DIRECT_TRAFFIC_TEST_KEY";
let _restore = Environment::capture(&[
key_name,
"PARSLEE_ACCESS_TOKEN",
car_auth::PARSLEE_API_BASE_KEY,
]);
let secret = car_secrets::SecretRef::with_default_service(key_name);
car_secrets::SecretStore::new()
.put(&secret, "synthetic-typesafe-key")
.unwrap();
unsafe {
std::env::set_var(key_name, "synthetic-wrong-env-key");
}
let typesafe = MockServer::start().await;
let parslee = MockServer::start().await;
let response = serde_json::json!({"model":"jev-latest","answers":{"label":{"type":"choice","choice":"billing","confidence":0.9,"probabilities":{"billing":0.9,"other":0.1}}},"usage":{"input_tokens":10,"output_tokens":2}});
Mock::given(method("POST"))
.and(path("/v1/systemone"))
.respond_with(ResponseTemplate::new(200).set_body_json(response.clone()))
.mount(&typesafe)
.await;
for signed_in in [false, true] {
unsafe {
std::env::set_var(car_auth::PARSLEE_API_BASE_KEY, parslee.uri());
if signed_in {
std::env::set_var("PARSLEE_ACCESS_TOKEN", "synthetic-parslee-token");
} else {
std::env::remove_var("PARSLEE_ACCESS_TOKEN");
}
}
let mut engine = engine_at(root.path());
*engine.unified.write().unwrap() = Arc::new(UnifiedRegistry::new_with_session(
root.path().to_path_buf(),
root.path().join("models"),
None,
registry::SessionProbe::Fixed(signed_in),
));
engine.register_model(direct_row(typesafe.uri(), key_name));
let scores = engine.classify(classify_request()).await.unwrap();
assert_eq!(scores[0].label, "billing");
assert_eq!(scores[0].score, 0.9);
let inferred = engine.generate_tracked(GenerateRequest {
model: Some("typesafe/test-direct".into()),
prompt: r#"{"state":"billing question","questions":{"label":{"type":"choice","criteria":{"other":"other","billing":"billing"}}}}"#.into(),
params: GenerateParams { strict_model: true, ..Default::default() },
..Default::default()
}).await.unwrap();
assert_eq!(
serde_json::from_str::<serde_json::Value>(&inferred.text).unwrap(),
response
);
assert_eq!(inferred.usage.unwrap().prompt_tokens, 10);
{
let mut tracker = engine.outcome_tracker.write().await;
for trace in tracker.pending_trace_ids() {
tracker.record_inferred_outcome(&trace, InferredOutcome::Inconclusive);
}
}
engine.flush_outcomes().await.unwrap();
}
let requests = typesafe.received_requests().await.unwrap();
assert_eq!(requests.len(), 4);
for request in requests {
assert_eq!(
request.headers.get("authorization").unwrap(),
"Bearer synthetic-typesafe-key"
);
assert_eq!(
request.body_json::<serde_json::Value>().unwrap()["model"],
"jev-latest"
);
if request.body_json::<serde_json::Value>().unwrap()["state"].is_string() {
let body = std::str::from_utf8(&request.body).unwrap();
assert!(
body.find(r#""other":"other""#).unwrap()
< body.find(r#""billing":"billing""#).unwrap()
);
}
}
assert!(parslee.received_requests().await.unwrap().is_empty());
assert!(engine_at(root.path()).concierge_actions(50).is_empty());
assert!(!root.path().join(action_ledger::ACTION_LEDGER_FILE).exists());
let log = std::fs::read_to_string(root.path().join("models/outcome_ledger.jsonl")).unwrap();
assert!(!log.contains("synthetic-typesafe-key"));
assert!(!log.contains("synthetic-wrong-env-key"));
let entries = outcome::read_ledger(&root.path().join("models/outcome_ledger.jsonl"), 0);
assert_eq!(entries.len(), 4);
assert!(entries.iter().all(|entry| {
let audit: serde_json::Value = serde_json::from_str(&entry.routing_reason).unwrap();
entry.model_id == "typesafe/test-direct"
&& audit["provider"] == "typesafe"
&& audit["provider_row"] == "typesafe/test-direct"
&& audit["key_id"] == key_name
}));
car_secrets::SecretStore::new().delete(&secret).unwrap();
}
#[tokio::test]
async fn typesafe_direct_fifty_calls_preserve_management_history() {
let _environment = openrouter::test_environment_scope_async().await;
let _home = openrouter::StateRootScope::new();
let root = tempfile::tempdir().unwrap();
let key_name = "TYPESAFE_DIRECT_HISTORY_TEST_KEY";
let secret = car_secrets::SecretRef::with_default_service(key_name);
let store = car_secrets::SecretStore::new();
store.put(&secret, "synthetic-history-key").unwrap();
let typesafe = MockServer::start().await;
Mock::given(method("POST"))
.and(path("/v1/systemone"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"answers":{"label":{"type":"choice","choice":"billing",
"probabilities":{"billing":0.9,"other":0.1}}}
})))
.mount(&typesafe)
.await;
let actions_path = root.path().join(action_ledger::ACTION_LEDGER_FILE);
for (seq, kind) in [ConciergeActionKind::Install, ConciergeActionKind::Rollback]
.into_iter()
.enumerate()
{
action_ledger::append_action(
&actions_path,
&ConciergeActionEntry {
seq: seq as u64 + 1,
kind,
model_id: "operator-model".into(),
use_case: Some(UseCase::Coding),
project: None,
prior_model_id: Some("prior-model".into()),
detail: "operator-approved change".into(),
timestamp: 100,
},
)
.unwrap();
}
let mut engine = engine_at(root.path());
engine.register_model(direct_row(typesafe.uri(), key_name));
let history = engine.concierge_actions(50);
let bytes = std::fs::read(&actions_path).unwrap();
for _ in 0..50 {
let scores = engine.classify(classify_request()).await.unwrap();
assert_eq!(scores[0].label, "billing");
assert_eq!(scores[0].score, 0.9);
}
{
let mut tracker = engine.outcome_tracker.write().await;
for trace in tracker.pending_trace_ids() {
tracker.record_inferred_outcome(&trace, InferredOutcome::Inconclusive);
}
}
engine.flush_outcomes().await.unwrap();
assert_eq!(engine.concierge_actions(50), history);
assert_eq!(std::fs::read(&actions_path).unwrap(), bytes);
assert_eq!(engine_at(root.path()).concierge_actions(50), history);
let audit_path = root.path().join("models/outcome_ledger.jsonl");
let entries = outcome::read_ledger(&audit_path, 0);
assert_eq!(entries.len(), 50);
assert!(entries.iter().all(|entry| {
let audit: serde_json::Value = serde_json::from_str(&entry.routing_reason).unwrap();
entry.model_id == "typesafe/test-direct"
&& entry.task == InferenceTask::Classify
&& audit["provider"] == "typesafe"
&& audit["provider_row"] == "typesafe/test-direct"
&& audit["key_id"] == key_name
}));
assert!(!std::fs::read_to_string(audit_path)
.unwrap()
.contains("synthetic-history-key"));
store.delete(&secret).unwrap();
}
#[tokio::test]
async fn typesafe_direct_missing_key_fails_named_without_network() {
let _environment = openrouter::test_environment_scope_async().await;
let _home = openrouter::StateRootScope::new();
let key = "TYPESAFE_ABSENT_DIRECT_TEST_KEY";
let _restore =
Environment::capture(&[key, "PARSLEE_ACCESS_TOKEN", car_auth::PARSLEE_API_BASE_KEY]);
let typesafe = MockServer::start().await;
let parslee = MockServer::start().await;
unsafe {
std::env::set_var(key, "synthetic-env-only-key");
std::env::set_var("PARSLEE_ACCESS_TOKEN", "synthetic-parslee-token");
std::env::set_var(car_auth::PARSLEE_API_BASE_KEY, parslee.uri());
}
let root = tempfile::tempdir().unwrap();
let mut engine = engine_at(root.path());
engine.register_model(direct_row(
typesafe.uri(),
"TYPESAFE_ABSENT_DIRECT_TEST_KEY",
));
let error = engine.classify(classify_request()).await.unwrap_err();
assert!(
error
.to_string()
.contains("TYPESAFE_ABSENT_DIRECT_TEST_KEY"),
"{error}"
);
let error = engine.generate_tracked(GenerateRequest {
model: Some("typesafe/test-direct".into()),
prompt: r#"{"state":"question","questions":{"urgent":{"type":"noul","instructions":"Urgent?"}}}"#.into(),
..Default::default()
}).await.unwrap_err();
assert!(error.to_string().contains(key), "{error}");
assert!(typesafe.received_requests().await.unwrap().is_empty());
assert!(parslee.received_requests().await.unwrap().is_empty());
}
#[tokio::test]
async fn typesafe_direct_status_uses_stored_presence_without_value_reads() {
let _environment = openrouter::test_environment_scope_async().await;
let home = openrouter::StateRootScope::new();
let key = "TYPESAFE_DIRECT_STATUS_TEST_KEY";
let _restore = Environment::capture(&[key]);
unsafe { std::env::set_var(key, "synthetic-env-only-key") };
let secret = car_secrets::SecretRef::with_default_service(key);
let store = car_secrets::SecretStore::new();
let mut registry = UnifiedRegistry::new_with_session(
home.path().to_owned(),
home.path().join("models"),
None,
registry::SessionProbe::Fixed(false),
);
registry.register(direct_row("https://api.typesafe.ai".into(), key));
let scope = car_secrets::ActivityScope::begin();
let before = scope.activity();
registry.refresh_availability();
assert!(!registry.get("typesafe/test-direct").unwrap().available);
assert_eq!(scope.activity().get_attempts, before.get_attempts);
registry.refresh_availability_for_explicit_status();
assert!(!registry.get("typesafe/test-direct").unwrap().available);
store.put(&secret, "synthetic-stored-key").unwrap();
let scope = car_secrets::ActivityScope::begin();
let before = scope.activity();
registry.refresh_availability_for_explicit_status();
assert!(registry.get("typesafe/test-direct").unwrap().available);
assert_eq!(scope.activity().get_attempts, before.get_attempts);
store.delete(&secret).unwrap();
}
#[tokio::test]
async fn typesafe_direct_refuses_header_overrides_and_redirects() {
let _environment = openrouter::test_environment_scope_async().await;
let _home = openrouter::StateRootScope::new();
let key = "TYPESAFE_DIRECT_HEADERS_TEST_KEY";
let secret = car_secrets::SecretRef::with_default_service(key);
let store = car_secrets::SecretStore::new();
store.put(&secret, "synthetic-stored-key").unwrap();
let typesafe = MockServer::start().await;
let redirected = MockServer::start().await;
Mock::given(method("POST"))
.respond_with(
ResponseTemplate::new(307)
.insert_header("location", format!("{}/stolen", redirected.uri())),
)
.mount(&typesafe)
.await;
let root = tempfile::tempdir().unwrap();
let mut engine = engine_at(root.path());
for name in ["Host", "Authorization", "bad header"] {
let mut row = direct_row(typesafe.uri(), key);
if let ModelSource::Proprietary { protocol, .. } = &mut row.source {
protocol
.extra_headers
.insert(name.into(), "synthetic-override".into());
}
engine.register_model(row);
let error = engine.classify(classify_request()).await.unwrap_err();
assert!(
error.to_string().contains("header") || error.to_string().contains("override"),
"{error}"
);
}
assert!(typesafe.received_requests().await.unwrap().is_empty());
engine.register_model(direct_row(typesafe.uri(), key));
let error = engine.classify(classify_request()).await.unwrap_err();
assert!(error.to_string().contains("307"), "{error}");
assert!(redirected.received_requests().await.unwrap().is_empty());
let result = engine
.generate_tracked_stream(GenerateRequest {
model: Some("typesafe/test-direct".into()),
prompt: "stream me".into(),
..Default::default()
})
.await;
let error = match result {
Err(error) => error,
Ok(_) => panic!("TypeSafe stream must refuse"),
};
assert!(error.to_string().contains("non-streaming"), "{error}");
assert_eq!(typesafe.received_requests().await.unwrap().len(), 1);
typesafe.reset().await;
Mock::given(method("POST"))
.respond_with(
ResponseTemplate::new(200)
.set_body_json(serde_json::json!({"echoed_key": "synthetic-stored-key"})),
)
.mount(&typesafe)
.await;
let error = engine.classify(classify_request()).await.unwrap_err();
assert!(error
.to_string()
.contains("invalid classification response"));
assert!(!error.to_string().contains("synthetic-stored-key"));
engine.flush_outcomes().await.unwrap();
let log = std::fs::read_to_string(root.path().join("models/outcome_ledger.jsonl")).unwrap();
assert!(!log.contains("synthetic-stored-key"));
store.delete(&secret).unwrap();
}