//! Run the OTLP `/v1/traces` receiver — POST a gen_ai trace, get back a sealed //! eval/1 receipt with a joule on it. //! //! ```text //! cargo run -p jcp-trace --example serve --features server -- 127.0.0.1:8090 & //! curl -s localhost:8090/v1/traces -d '{"trace":{"resourceSpans":[{"scopeSpans":[{"spans":[ //! {"traceId":"a","spanId":"s1","name":"chat","attributes":[ //! {"key":"gen_ai.operation.name","value":{"stringValue":"chat"}}, //! {"key":"gen_ai.usage.output_tokens","value":{"intValue":"64"}}]}]}]}]}, //! "assessments":[{"name":"correctness","source":"llm_judge","value":"pass"}]}' //! ``` use std::net::TcpListener; use ed25519_dalek::SigningKey; use jcp_trace::{server, Gate}; fn main() -> std::io::Result<()> { let addr = std::env::args().nth(1).unwrap_or_else(|| "127.0.0.1:8090".to_string()); let listener = TcpListener::bind(&addr)?; eprintln!("jcp-trace OTLP receiver: http://{addr}/v1/traces"); // Seal under one steward; every posted run is judged against this gate and // priced at 12 µJ/token where a span carries no measured reading. let sk = SigningKey::from_bytes(&[9u8; 32]); let gate = Gate::require_pass(["correctness", "safety"]); let mut srv = server::EvalServer::new(sk, "did:example:trace-receiver", gate, 12); server::run(&listener, &mut srv) }