> ## Documentation Index
> Fetch the complete documentation index at: https://docs.westyx.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust SDK

> Official Rust SDK for Westyx Nexus - synchronous, thread-safe, no async runtime required.

Official Rust SDK for [Westyx Nexus](https://westyx.dev) - the centralised secrets, feature flags, and config service.

```rust theme={null}
use westyx_nexus::{NexusClient, NexusConfig};
use std::time::Duration;

let client = NexusClient::create(NexusConfig {
    api_key: std::env::var("NEXUS_API_KEY").unwrap(),
    endpoint: "https://blue-ocean-a5rx7.westyx.dev".to_string(),
    ttl: Some(Duration::from_secs(60)),
    wif: None,
})?;

client.run_stream(); // SSE live updates - non-blocking

let db_url = client.get_config("database.url");
let stripe_key = client.get_secret("stripe.key")?;
let enabled = client.get_flag("new.checkout", false);
```

## Highlights

* **Rust 1.75+** - synchronous blocking API, **no async runtime required**
* **Clone is cheap** (`Arc` bump) - pass clones freely to threads, tokio tasks, and actix/axum handlers
* **Thread-safe TTL cache** - `Arc<Mutex<CacheState>>` snapshot, all clones see the same live cache
* **ETag/304 support** - no payload downloaded when nothing has changed
* **SSE live updates** via `run_stream()` - non-blocking, spawns a background `std::thread`; propagates remote changes within milliseconds; falls back to TTL polling after 3 transport errors
* **Public-key vs secret-key access control** - public-key clients get `PublicKeyRestricted` from `get_secret` before any network call
* **Pattern-match on `NexusError`** - idiomatic Rust enum variants, no string matching
* **Workload Identity Federation** - Kubernetes / AWS IRSA / GCP / Azure auto-detected; bearer-JWT auth with automatic refresh; **AWS IAM (`aws_iam`)** for ECS/Fargate/Lambda/plain-EC2 *(v0.9.0-beta.1, `aws-iam` feature)*
* **Write API** - `set_secret`, `delete_secret`, `delete_secret_version` (SK key only)
* **A/B testing** - `evaluate_ab` for the AB Testing add-on; `AbAddonNotAvailable` on 403
* **File-type secrets** - `get_secret_file_path` exposes a `PathBuf`; temp files cleaned up on `Drop` when the last clone is dropped
* **`ureq` v2** for HTTP - small, dependency-light, no tokio

## What's new in v0.10.1-beta.1

* **Public-key error message no longer mentions the retired `pk_` prefix** - the error surfaced when a public-key client attempts a secret operation now reads "cannot read or write secrets with a public key", completing the R12 prefix rebrand across user-facing strings.

## What's new in v0.9.0-beta.1

* **`aws_iam` WIF provider (AWS IAM Caller Identity)** - authenticates non-EKS AWS compute (**ECS/Fargate, Lambda, plain EC2**) that has IAM credentials but no OIDC token. The SDK SigV4-signs an STS `GetCallerIdentity` request (never sent to AWS) and posts it to `/v1/auth/token-exchange`; Nexus replays it against a pinned STS endpoint to prove your IAM role. The signed `X-Nexus-Server-ID` is your service's own endpoint host - a captured request is valid for that one service only. Behind the optional `aws-iam` cargo feature (`aws-config` + `aws-sigv4`), off by default. See [Workload identity](workload-identity#aws-iam-non-eks-aws-compute-v090-beta1).
* **Azure IMDS path** - the `azure` provider prefers the projected federated token file (`$AZURE_FEDERATED_TOKEN_FILE`, AKS) and otherwise fetches an IMDS managed-identity token, requiring an explicit `api://<client-id>` audience (the generic default is refused).
* **Security hardening** - `NexusClient` rejects plain-http endpoints (loopback excepted); a failed WIF refresh fails closed (never a stale token); token-exchange 400/403 map to `BadRequest`/`Forbidden`; the slug `Host` header is sent on the exchange; metadata/exchange reads are bounded; `expires_in` is clamped.

## What's new in v0.8.0-beta.2

* **WIF GCP fix** - the `gcp` provider now fetches a real Google-signed OIDC identity token from the GCE metadata server. It previously read the `GOOGLE_APPLICATION_CREDENTIALS` key file, which is not a JWT and was rejected by the token exchange. Auto-detection was aligned with the actual token sources.

## What's new in v0.8.0-beta.1

* **Version alignment** - bumped to v0.8.0-beta.1 to align with the Nexus SDK suite. No functional changes.
* **OpenFeature provider planned** - `westyx-nexus-openfeature` crate is planned but deferred until the `open-feature` crate is available on crates.io.

## What's new in v0.5.1-beta.1

* **Security improvements** - exception messages contain only HTTP status codes; WIF tokens stripped of whitespace; file-type secret paths are opaque hashes.
* **`flag.toggled` SSE event** - flag toggle events now trigger a cache re-sync.
* **SSE quarantine detection** - stream 429 with quarantine body correctly pauses reconnects until `expires_at`.
* **Drop cleanup fix** - file-type secrets reliably removed when the last client clone is dropped.

## What's new in v0.5.0-beta.1

Initial Rust SDK release.

## Install

```sh theme={null}
cargo add westyx-nexus
```

Latest release: **v0.10.1-beta.1** *(2026-07-10 - drops the retired `pk_` prefix from the public-key error message)*.

## Quick start

```rust theme={null}
use westyx_nexus::{NexusClient, NexusConfig, NexusError};
use std::time::Duration;

fn main() -> Result<(), NexusError> {
    let client = NexusClient::create(NexusConfig {
        api_key: std::env::var("NEXUS_API_KEY").unwrap_or_default(),
        endpoint: std::env::var("NEXUS_URL").expect("NEXUS_URL not set"),
        ttl: Some(Duration::from_secs(60)),
        wif: None,
    })?;

    // Optionally enable SSE live updates (non-blocking)
    client.run_stream();

    // Configs
    if let Some(db_url) = client.get_config("database.url") {
        println!("db url: {}", db_url);
    }

    // Secrets (secret key required)
    let stripe_key = client.get_secret("stripe.key")?;
    println!("stripe key: {} bytes", stripe_key.len());

    // Feature flags
    let new_ui = client.get_flag("new.ui", false);
    println!("new UI enabled: {}", new_ui);

    Ok(())
}
```

## Pages

| Page                                   | Description                                                       |
| -------------------------------------- | ----------------------------------------------------------------- |
| [Installation](installation)           | `cargo add` flow, `Cargo.toml` dependency, minimum Rust version   |
| [Configuration](configuration)         | `NexusConfig` field reference, TTL guidance, `WifConfig` overview |
| [API reference](api-reference)         | Every public method and type                                      |
| [Error handling](error-handling)       | `NexusError` enum variants, match patterns, failure scenarios     |
| [SSE live updates](sse-live-updates)   | `run_stream()` semantics, reconnection, backoff                   |
| [Caching behaviour](caching-behaviour) | When does the SDK hit the network                                 |
| [Workload identity](workload-identity) | WIF with Kubernetes, AWS, GCP, and Azure                          |
