liteguard 0.7.20260603

Feature guards, observability, and security response in a single import. Evaluated locally, zero network overhead per check
Documentation

liteguard

Rust SDK crates.io docs.rs License

Feature guards, observability, and security response in a single import. Evaluated locally, zero network overhead per check.

Liteguard for Rust. Initialize one process-scoped Client, then create explicit immutable request Scopes for per-request properties and protected context.


Installation

[dependencies]
liteguard = "0.7"

Quick Start

use liteguard::{Client, ClientOptions, Options, Properties, ProtectedContext};
use std::collections::HashMap;

#[tokio::main]
async fn main() {
    let client = Client::init("pct-...", ClientOptions {
        environment: Some("env-production".into()),
        ..Default::default()
    })
    .await
    .unwrap();

    let scope = client.create_scope(
        Properties::new()
            .set("user_id", "user-123")
            .set("plan", "pro")
            .set("region", "us-east-1"),
    );

    if scope.is_open("payments.checkout") {
        // guard is open
    }

    let protected_scope = scope
        .bind_protected_context(ProtectedContext {
            properties: HashMap::from([("email".to_string(), "alice@acme.com".to_string())]),
            signature: "sig-123".into(),
            issued_at: None,
            expires_at: None,
        })
        .await
        .unwrap();

    let session = protected_scope.execute_if_open("payments.checkout", || {
        create_checkout_session()
    });

    if session.is_none() {
        // guard was closed
    }

    client.shutdown().await.unwrap();
}

Request Scoping

The core Rust API is scope-first:

  • Client is process-scoped and shared
  • Scope is immutable and request-scoped
  • ordinary properties live on Scope
  • protected context binds a derived Scope and may fetch or reuse a cached protected bundle

Create derived scopes with ordinary properties:

use liteguard::Properties;

let base = client.create_scope(Properties::new().set("request_id", "req-123"));
let pro_scope = base.with_properties(Properties::new().set("plan", "pro"));
let cleared = pro_scope.clear_properties(&["plan"]);

Bind protected context per request:

use liteguard::ProtectedContext;
use std::collections::HashMap;

let protected = scope
    .bind_protected_context(ProtectedContext {
        properties: HashMap::from([("email".to_string(), "alice@acme.com".to_string())]),
        signature: "sig-123".into(),
        issued_at: None,
        expires_at: None,
    })
    .await?;

let public_again = protected.clear_protected_context().await?;

API Reference

Client::init(project_client_token, options) -> Result<Client>

Initializes the SDK, performs the initial public-bundle fetch, then starts background refresh and signal flush tasks.

client.create_scope(properties) -> Scope

Creates a request scope with the provided ordinary properties.

scope.evaluate(name) -> GuardDecision

Returns a GuardDecision containing the full evaluation result: is_open, name, adopted, reason, matched_rule_index, and properties.

scope.is_open(name) -> bool

Evaluates a guard for that request scope and emits a guard_check signal.

scope.is_open_with_options(name, options) -> bool

Evaluates a guard with per-call property overrides merged on top of the scope's properties.

scope.peek_is_open(name) -> bool

Read-only evaluation without emitting telemetry or consuming a rate-limit slot.

scope.execute_if_open(name, f) -> Option<T>

Evaluates the guard and executes f only when it is open. Emits both guard_check and guard_execution telemetry.

scope.try_execute_if_open(name, f) -> Result<Option<T>, E>

Explicit fallible variant of guarded execution. Returns Ok(None) when the guard is closed, Ok(Some(value)) when the guard is open and f succeeds, and Err(error) when the guard is open but f fails.

scope.bind_protected_context(protected_context).await -> Result<Scope>

Returns a derived request scope using a protected bundle keyed by the protected-context fingerprint.

scope.clear_protected_context().await -> Result<Scope>

Returns a derived request scope back on the public bundle.

scope.start_execution() -> Scope

Creates an execution correlation handle for linking related guard checks and signals.

scope.get_properties() -> Properties

Returns the current property bag for the scope. Useful for serializing and transporting properties across service boundaries.

client.flush().await

Flushes buffered signals immediately.

client.shutdown().await

Stops background tasks and flushes buffered signals.


Guard Evaluation

Rules are evaluated in order, first matching rule wins. If no rule matches, the guard's default applies.

Operators

Operator Description
EQUALS Exact match
NOT_EQUALS Negated exact match
IN Value in a set
NOT_IN Value not in a set
REGEX Regular expression match
GT / GTE Greater than / greater or equal
LT / LTE Less than / less or equal

Development

Build-time auto-instrumentation via the Liteguard CLI injects guard points around third-party call sites during the build step.

make test-rust

License

Apache 2.0 see LICENSE.