use traverse_contracts::ExecutionTarget;
use traverse_registry::{
ModelCandidateEvaluation, ModelCandidateReadiness, ModelCandidateRejectionCode,
ModelResolutionEvidence, ModelResolutionPhase, SelectedModelCandidate,
};
use traverse_runtime::trace::{
PrivateTraceEntry, PublicTraceEntry, TraceOutcome, TraceStore, new_trace_id_and_time,
};
fn make_public(capability_id: &str) -> PublicTraceEntry {
let (id, time) = new_trace_id_and_time();
PublicTraceEntry::new(
id,
capability_id.to_string(),
"cloud".to_string(),
TraceOutcome::Success,
42,
time,
)
}
fn make_private(trace_id: &str) -> PrivateTraceEntry {
PrivateTraceEntry::new(
trace_id.to_string(),
"raw input bytes",
"raw output bytes",
42,
)
}
#[test]
fn public_trace_entry_has_all_cloudevents_fields() {
let entry = make_public("content.comments.create-comment-draft");
assert!(!entry.id.is_empty(), "id must be non-empty");
assert!(!entry.source.is_empty(), "source must be non-empty");
assert!(!entry.event_type.is_empty(), "event_type must be non-empty");
assert!(
!entry.datacontenttype.is_empty(),
"datacontenttype must be non-empty"
);
assert!(!entry.time.is_empty(), "time must be non-empty");
}
#[test]
fn public_trace_entry_source_contains_capability_id() {
let entry = make_public("my.cap.id");
assert!(
entry.source.contains("my.cap.id"),
"source '{}' should contain capability id",
entry.source
);
assert_eq!(entry.event_type, "dev.traverse.execution.completed");
assert_eq!(entry.datacontenttype, "application/json");
}
#[test]
fn private_entry_hashes_are_sha256_hex() {
let (id, _) = new_trace_id_and_time();
let priv_entry = make_private(&id);
assert_eq!(
priv_entry.inputs_hash.len(),
64,
"inputs_hash must be 64 hex chars"
);
assert_eq!(
priv_entry.outputs_hash.len(),
64,
"outputs_hash must be 64 hex chars"
);
assert!(
priv_entry
.inputs_hash
.chars()
.all(|c| c.is_ascii_hexdigit()),
"inputs_hash must be hex"
);
assert!(
priv_entry
.outputs_hash
.chars()
.all(|c| c.is_ascii_hexdigit()),
"outputs_hash must be hex"
);
}
#[test]
fn no_raw_input_in_any_trace_field() {
let raw = "super-secret-input-data";
let (id, time) = new_trace_id_and_time();
let public = PublicTraceEntry::new(
id.clone(),
"cap.id".to_string(),
"cloud".to_string(),
TraceOutcome::Success,
1,
time,
);
let private = PrivateTraceEntry::new(id.clone(), raw, "output", 1);
let serialized = serde_json::to_string(&public).unwrap_or_default();
assert!(
!serialized.contains(raw),
"raw input must not appear in public trace"
);
assert!(
!private.inputs_hash.contains(raw),
"raw input must not appear in private hash field"
);
}
#[test]
fn public_trace_entry_exposes_redacted_model_resolution_evidence() {
let mut public = make_public("traverse.inference.generate");
public.model_resolution.push(model_resolution_evidence());
let serialized = serde_json::to_string(&public).unwrap_or_default();
assert!(serialized.contains("model_resolution"));
assert!(serialized.contains("ollama.local.generate"));
assert!(serialized.contains("llama3.2:3b"));
assert!(!serialized.contains("private prompt"));
assert!(!serialized.contains("raw source text"));
assert!(!serialized.contains("sk-local-secret"));
}
#[test]
fn get_trace_without_private_flag_returns_public_only() -> Result<(), String> {
let mut store = TraceStore::new();
let pub_entry = make_public("cap.a");
let trace_id = pub_entry.id.clone();
let priv_entry = make_private(&trace_id);
store.insert(pub_entry, Some(priv_entry));
let (public, private) = store
.get(&trace_id)
.ok_or_else(|| "trace must exist".to_string())?;
assert_eq!(public.capability_id, "cap.a");
let _ = private; Ok(())
}
#[test]
fn get_trace_with_private_flag_returns_both_tiers() -> Result<(), String> {
let mut store = TraceStore::new();
let pub_entry = make_public("cap.b");
let trace_id = pub_entry.id.clone();
let priv_entry = make_private(&trace_id);
store.insert(pub_entry, Some(priv_entry));
let (public, private) = store
.get(&trace_id)
.ok_or_else(|| "trace must exist".to_string())?;
assert_eq!(public.capability_id, "cap.b");
assert!(private.is_some(), "private tier must be present");
let priv_ref = private.ok_or_else(|| "private tier must be present".to_string())?;
assert_eq!(priv_ref.trace_id, trace_id);
Ok(())
}
#[test]
fn get_trace_with_no_private_tier_returns_none() -> Result<(), String> {
let mut store = TraceStore::new();
let pub_entry = make_public("cap.c");
let trace_id = pub_entry.id.clone();
store.insert(pub_entry, None);
let (_, private) = store
.get(&trace_id)
.ok_or_else(|| "trace must exist".to_string())?;
assert!(private.is_none());
Ok(())
}
#[test]
fn list_traces_filtered_by_capability_id() {
let mut store = TraceStore::new();
store.insert(make_public("cap.x"), None);
store.insert(make_public("cap.x"), None);
store.insert(make_public("cap.y"), None);
let x_results = store.list_public(Some("cap.x"));
assert_eq!(x_results.len(), 2);
let y_results = store.list_public(Some("cap.y"));
assert_eq!(y_results.len(), 1);
let all_results = store.list_public(None);
assert_eq!(all_results.len(), 3);
}
#[test]
fn unknown_trace_id_returns_none() {
let store = TraceStore::new();
assert!(store.get("nonexistent-id").is_none());
}
fn model_resolution_evidence() -> ModelResolutionEvidence {
ModelResolutionEvidence {
phase: ModelResolutionPhase::Execution,
interface_id: "traverse.inference.generate".to_string(),
requested_interface_id: "traverse.inference.generate".to_string(),
requested_placement: ExecutionTarget::Local,
selected: Some(SelectedModelCandidate {
candidate_id: "ollama-llama-3-2".to_string(),
provider_capability_id: "traverse.inference.generate".to_string(),
provider_implementation_id: "ollama.local.generate".to_string(),
model_identifier: "llama3.2:3b".to_string(),
placement_target: ExecutionTarget::Local,
priority: 10,
selection_reason: "selected highest-priority passing candidate".to_string(),
}),
candidates: vec![ModelCandidateEvaluation {
candidate_id: "ollama-llama-3-2".to_string(),
provider_capability_id: "traverse.inference.generate".to_string(),
provider_implementation_id: "ollama.local.generate".to_string(),
model_identifier: "llama3.2:3b".to_string(),
placement_target: ExecutionTarget::Local,
priority: 10,
readiness: ModelCandidateReadiness::Ready,
rejection_code: Option::<ModelCandidateRejectionCode>::None,
reason: "candidate passed availability, interface, placement, and context checks"
.to_string(),
manifest_order: 0,
}],
failure_code: Option::<ModelCandidateRejectionCode>::None,
}
}