# liteguard
[](https://github.com/liteguard/liteguard/actions/workflows/test-rust-sdk.yml)
[](https://crates.io/crates/liteguard)
[](https://docs.rs/liteguard)
[](https://github.com/liteguard/liteguard/blob/main/LICENSE)
- Website: [liteguard.io](https://liteguard.io)
- Project Page: [https://github.com/liteguard/liteguard](https://github.com/liteguard/liteguard)
- Issues: [https://github.com/liteguard/liteguard/issues/new](https://github.com/liteguard/liteguard/issues/new)
> 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 `Scope`s for per-request properties and protected context.
---
## Installation
```toml
[dependencies]
liteguard = "0.7"
```
---
## Quick Start
```rust
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:
```rust
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:
```rust
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
| `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](https://github.com/liteguard/liteguard/tree/main/cli) injects guard points around third-party call sites during the build step.
```bash
make test-rust
```
---
## License
Apache 2.0 see [LICENSE](https://github.com/liteguard/liteguard/blob/main/LICENSE).