CleanLibrary Rust SDK
cleanlib-client is the Rust client library for CleanLibrary. It wraps the same HTTP surface that powers the CLI, the MCP server, and the VS Code extension behind a small, typed API you can drop into any Rust program — a service, a CLI tool, a CI gate, or an admission controller.
1. What it does
The Rust SDK answers the same package-manager-layer questions as the CLI, but from inside a Rust program rather than from a shell:
- Is this version safe to install? —
client.fetch_verdict(...) - What does my policy do with this package? —
client.policy_preview(...) - Fetch the verified upstream bytes —
client.fetch_artifact(...)
The wire contract is identical to every other CleanLibrary client. A verdict returned by the Rust SDK has the same shape as a verdict returned by the CLI or the MCP server, so you can mix-and-match clients within one workflow.
2. Install
cargo add cleanlib-client
Or in your Cargo.toml:
[dependencies]
cleanlib-client = "0.1"
tokio = { version = "1", features = ["full"] }
The SDK targets Rust 1.75+ and uses tokio + reqwest for transport. cleanlib-client is the same library that powers cleanlib-cli; using it directly gives you the same wire contract without the binary.
3. Quickstart
v0.1.1+ re-exports the canonical types at the crate root — Client, Verdict, and PolicyDecision are all available via use cleanlib_client::{Client, Verdict, PolicyDecision}; directly.
use cleanlib_client::{Client, Verdict};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new(
"https://cleanapp.clnstrt.dev",
Some(std::env::var("CLEANLIB_API_KEY")?),
)?;
let verdict: Verdict = client
.fetch_verdict("npm", "lodash", "4.17.21")
.await?;
println!("verdict_id: {}", verdict.verdict_id);
println!("severity: {:?}", verdict.severity);
println!("source: {}", verdict.source);
Ok(())
}
Output:
verdict_id: <stable-identifier>
severity: Some("NONE")
source: ALLOWED_NO_FINDINGS
4. Configuration
Client::new takes the endpoint and an optional api_key. For richer configuration use Client::from_config(&Config).
| Field | Purpose | Default |
|---|---|---|
endpoint (positional) | Base URL of the CleanLibrary backend | (required) |
api_key (positional Option<String>) | Bearer token (typically from CLEANLIB_API_KEY env var) | None |
Config { api_version, timeout, http_client, .. } | Richer-knob configuration via Client::from_config | sensible defaults |
The convention for production deployments is to read endpoint and API key from environment variables:
let client = Client::new(
&std::env::var("CLEANLIB_ENDPOINT")?,
Some(std::env::var("CLEANLIB_API_KEY")?),
)?;
5. API reference
Client::fetch_verdict(ecosystem, package, version) -> Result<Verdict>
Returns a verdict for a single (ecosystem, package, version) tuple.
pub struct Verdict {
pub verdict_id: String, // stable identifier for this decision
pub verdict: String, // ALLOWED_NO_FINDINGS | VECTOR_VERDICT | DM_THRESHOLD_BLOCK | INSUFFICIENT_DATA
pub source: String, // mirrors `verdict` on v0.4.x
pub confidence: f64,
pub composite_score: u8, // 0-100 confidence in the decision
pub severity: Option<String>, // NONE | LOW | MEDIUM | HIGH | CRITICAL
pub reasoning: String,
pub suggested_actions: Vec<String>,
pub data_freshness_at: Option<String>,
// Plus similar_to, evidence_gaps, computed_at, attestation, and rich-data fields
}
Client::policy_preview(...)
Returns what your candidate policy would decide for the given packages, with the matching policy rule attached. Useful for "if I add this rule, will it break my CI?" checks.
Client::fetch_artifact(ecosystem, package, version) -> Result<Bytes>
Returns the verified upstream bytes for an (ecosystem, package, version) tuple.
Client::fetch_artifact_stream(ecosystem, package, version, writer) -> Result<()>
Streams the upstream bytes to a writer — useful for large artifacts where buffering the full byte vector is undesirable.
Client::audit(...)
Returns the customer-side audit log for a time window.
derive_status(source, severity) -> DerivedStatus
Helper function that computes a renderable DerivedStatus from a verdict's source and severity fields. Available via use cleanlib_client::derive_status;.
6. Error handling
The SDK returns Result<T, CleanLibraryError>. Common error variants:
| Variant | When it surfaces |
|---|---|
CleanLibraryError::Authentication { .. } | Missing, malformed, or rejected api_key |
CleanLibraryError::PackageNotFound { .. } | The catalog has no verdict for this (ecosystem, package, version) yet |
CleanLibraryError::PolicyDeny { .. } | A 403 with a verdict-attached policy-deny envelope |
CleanLibraryError::RiskAcceptanceRequired { .. } | A 403 indicating the customer must record risk-acceptance |
CleanLibraryError::RateLimit { retry_after } | A 429 with Retry-After set |
CleanLibraryError::Transport(...) | Network, DNS, or TLS failure — wraps the underlying reqwest::Error |
A Verdict is not an error — it's a successful response with a verdict-aware shape. Use the verdict's source and severity to drive flow control, not ?.
7. CI integration
Drop the SDK into a build step and exit non-zero on a denied verdict:
// build/precheck/src/main.rs
use cleanlib_client::Client;
#[tokio::main]
async fn main() {
let client = Client::new(
&std::env::var("CLEANLIB_ENDPOINT").unwrap(),
Some(std::env::var("CLEANLIB_API_KEY").unwrap()),
).unwrap();
let v = client.fetch_verdict("npm", "lodash", "4.17.21").await.unwrap();
if v.source == "DM_THRESHOLD_BLOCK" {
eprintln!("BLOCKED: npm/lodash@4.17.21 — {}", v.reasoning);
std::process::exit(1);
}
}
8. Versioning
The SDK follows Semantic Versioning. The verdict envelope wire contract is stable across the v0.1 series — clients can mix v0.1.0 and v0.1.1 against the same backend without coordination.
v0.1.x envelopes are byte-identical with the Python, Go, and JavaScript SDKs against the same backend version — verdicts produced by each SDK derive the same status for the same (ecosystem, package, version) tuple. cleanlib-client shares its codebase with cleanlib-cli, so the binary and the library always agree.
9. Where to go next
- CLI — the same verdicts and remediation surface from the terminal, for ad-hoc queries and CI gates
- MCP Server — surface CleanLibrary inside any MCP-compatible AI coding agent
- SDK — Go — Go programmatic access to the same verdict surface
- SDK — Python — Python programmatic access
- SDK — JavaScript — JavaScript / TypeScript programmatic access
- Integration Surfaces — the full integration matrix (admission, CI, IDE, agent)
- Architecture — how CleanLibrary's verdict-and-enrichment surface composes end to end