SDKs

Rust SDK

Quickstart for the Lattix Rust SDK — the canonical core for embedded enforcement, exposing the full /v1/sdk/* control-plane surface.

The Rust SDK is the canonical core of the Lattix SDK family. It owns the HTTP behavior, typed request/response models, and the C ABI consumed by the Go and Python bindings. Applications can use it directly, or they can use a higher-level language binding that wraps it.

This page is a conceptual quickstart. Full API reference — every public type, every field, every example — lives with the crate itself at docs.rs/sdk-rust and in the crate's README.md.

Install

cargo add sdk-rust

The crate publishes to crates.io. Tagged GitHub releases additionally attach version-matched native artifacts (Linux x86_64, macOS x86_64, macOS aarch64, Windows x86_64) for non-Cargo consumers and the Go/Python bindings.

Construct a client

The SDK uses a builder pattern rooted at Client::builder(base_url).

use sdk_rust::Client;

let client = Client::builder("https://api.lattix.io")
    .with_bearer_token("<your-token>")
    .with_tenant_id("<your-tenant>")
    .with_user_id("<your-user>")
    .build()?;

Supported builder options:

MethodPurpose
.with_bearer_token(token)Attach a pre-issued bearer token to every request.
.with_client_id(id) / .with_client_secret(secret)Use SDK client credentials; the SDK will exchange them for a short-lived token on first use and cache it.
.with_tenant_id(tenant)Attach the tenant identity for this client instance. Required in client-credentials mode.
.with_user_id(user)Attach the user/principal identity (used in trusted-headers deployments).
.with_timeout_secs(n)Set the HTTP request timeout.
.with_token_exchange_path(path)Override the default session-exchange endpoint path.
.with_requested_scopes(scopes)Request specific scopes during session exchange.
.with_header(name, value)Attach an arbitrary header to every request.

A built client is thread-safe and reusable across operations.

Make a call

Every operation on the Client is a blocking method that returns Result<T, SdkError>.

use sdk_rust::{
    ArtifactProfile, ProtectionOperation, ResourceDescriptor, SdkProtectionPlanRequest,
    WorkloadDescriptor,
};
use std::collections::BTreeMap;

// 1. Discovery: confirm connectivity and capabilities.
let bootstrap = client.bootstrap()?;
println!("enforcement model: {}", bootstrap.enforcement_model);

// 2. Metadata-only planning: ask the platform for a protection plan.
let plan = client.protection_plan(&SdkProtectionPlanRequest {
    operation: ProtectionOperation::Protect,
    workload: WorkloadDescriptor {
        application: "example-app".to_string(),
        environment: Some("prod".to_string()),
        component: Some("ingest".to_string()),
    },
    resource: ResourceDescriptor {
        kind: "document".to_string(),
        id: Some("doc-123".to_string()),
        mime_type: Some("application/pdf".to_string()),
    },
    preferred_artifact_profile: Some(ArtifactProfile::Tdf),
    content_digest: Some("sha256:...".to_string()),
    content_size_bytes: Some(1024),
    purpose: Some("store".to_string()),
    labels: vec!["confidential".to_string()],
    attributes: BTreeMap::new(),
})?;

// 3. Use the plan to enforce locally.
if plan.decision.allow && plan.execution.protect_locally {
    // ... perform local protection using the indicated artifact profile
}

The SDK returns a SdkProtectionPlanResponse whose execution block tells the caller how to protect the object locally. The platform does not receive plaintext at any point.

The eight operations

Every method on Client maps to a single /v1/sdk/* route.

client.capabilities()?;                      // GET /v1/sdk/capabilities
client.whoami()?;                            // GET /v1/sdk/whoami
client.bootstrap()?;                         // GET /v1/sdk/bootstrap
client.exchange_session()?;                  // POST /v1/sdk/session (client-credentials mode only)
client.protection_plan(&req)?;               // POST /v1/sdk/protection-plan
client.policy_resolve(&req)?;                // POST /v1/sdk/policy-resolve
client.key_access_plan(&req)?;               // POST /v1/sdk/key-access-plan
client.artifact_register(&req)?;             // POST /v1/sdk/artifact-register
client.evidence(&req)?;                      // POST /v1/sdk/evidence

See Platform API → Endpoints for the shape of each request and response.

Errors

The single public error type is SdkError, a Debug + Display + std::error::Error enum. Callers typically match on:

VariantWhen
SdkError::InvalidInputBuilder misconfiguration or a bad request field (client-side).
SdkError::ConnectionNetwork-level failure reaching the platform.
SdkError::ServerThe platform returned a non-success HTTP status.
SdkError::SerializationRequest could not be serialized or response could not be decoded.
SdkError::IoUnderlying I/O error (rare in normal flows).

Using the native library outside Cargo

Because the crate builds as rlib, cdylib, and staticlib, the same native library can be consumed from any language that can call a C ABI. The canonical header is published at include/lattix_sdk.h in the crate and in each release bundle.

The C ABI contract:

  • All exported functions use UTF-8 JSON payloads and JSON string responses.
  • Strings returned by the library must be released with lattix_sdk_string_free(...).
  • Client handles returned by lattix_sdk_client_new(...) must be released with lattix_sdk_client_free(...).
  • Null returns indicate failure; call lattix_sdk_last_error_message() for a thread-local error string.

The Go and Python bindings in this SDK family are built against that same ABI.

Relationship to other pages