Skip to main content
Official Rust SDK for Westyx Nexus - the centralised secrets, feature flags, and config service.

Highlights

  • Async-first - tokio + reqwest, TLS via rustls, so no OpenSSL system dependency
  • Cache reads stay synchronous - they read in-memory state, so there is no .await to write and nothing to block on
  • blocking feature - the same surface synchronously for applications with no runtime of their own; it works even inside another runtime
  • tracing diagnostics - spans and structured events, a no-op until you install a subscriber, and no credential is ever recorded
  • Clone is cheap (Arc bump) - pass clones freely to tasks and to axum/actix handlers
  • Thread-safe TTL cache - one snapshot shared by every clone; concurrent reads on a stale snapshot trigger a single coalesced refresh
  • ETag/304 support - nothing is downloaded when nothing has changed
  • SSE live updates via run_stream() - a tokio task with a connect deadline and an idle deadline that resets on every byte; falls back to TTL polling after 3 transport errors and retries on a schedule
  • Public-key vs secret-key access control - public-key clients get PublicKeyRestricted before any network call, and both secret accessors refuse a frontend-kind service
  • Owner-only file-type secrets - materialised 0600 into a private 0700 directory per client; removed on close() or when the last clone is dropped
  • Pattern-match on NexusError - idiomatic enum variants, #[non_exhaustive], no string matching
  • Workload Identity Federation - Kubernetes / AWS IRSA / GCP / Azure auto-detected, plus AWS IAM (aws_iam) for ECS/Fargate/Lambda/plain EC2 behind a feature flag, a developer provider for local machines, and a custom credential source for everything else
  • Write API - set_secret, delete_secret, delete_secret_version (secret key only)
  • A/B testing - evaluate_ab; AbAddonNotAvailable on 403
  • OpenFeature - the separate westyx-nexus-openfeature crate wraps an existing client

What’s new in v0.14.0-beta.2

  • Three declared dependency floors raised to versions that actually build. serde_json to 1.0.25, tempfile to 3.10.0, and the dev-only mockito to 1.3.0 - a -Z minimal-versions build now runs every pipeline, so a declared floor cannot silently stop building again.

What’s new in v0.14.0-beta.1

  • Breaking: secrets are SecretString. get_secret returns a secrecy::SecretString, read with .expose_secret() (both re-exported from the crate root). The value is zeroised on drop - so a replaced cache snapshot leaves no plaintext in freed memory - and Debug renders it as [REDACTED].
  • Credential-bearing requests refuse redirects. The API and stream clients set redirect::Policy::none(), so a 3xx never resends the API key or the WIF session token to another host.
  • The public-key guard honours the backend’s classification. A key the backend reports as public is refused secret access whether or not it carries the wxp_ prefix - either signal is sufficient.
  • The developer credential is matched on host and port, so two local services on the same host but different ports resolve to their own sessions.

What’s new in v0.13.0-beta.1

  • A typed provider vocabulary. WifProvider is a #[non_exhaustive] enum implementing Display and FromStr, so a provider read out of an environment variable is validated where it is read rather than deep inside a session refresh.
  • Breaking: one credential field. WifConfig.provider and WifConfig.token_source collapse into credential: WifCredential, so a provider and a custom source cannot both be configured. See Workload identity for the one-line migration per break.
  • An async credential source that can express a whole exchange body. WifCredentialSource produces either an OIDC token or the complete token-exchange payload, so a credential that is not an OIDC token fits without a change to the SDK. blocking_token_source adapts an existing synchronous closure.
  • The developer provider. On a machine where westyx dev setup has run, the SDK sends the Nexus session token the CLI already obtained. It performs no token exchange and is probed last, so a real cloud credential always wins.
  • Contradictions rejected at construction, naming the fix: aws_region outside aws_iam, and aws_iam without the aws-iam cargo feature.
  • Printing a NexusConfig or a WifConfig renders the API key as set/unset.

What’s new in v0.12.0-beta.1

  • The OpenFeature provider resolves boolean flags per user. An evaluation context carrying a targeting key selects a per-user evaluation through the A/B Testing add-on, so rollout percentages and cohort rules apply. One request covers every flag in the snapshot, results are memoised per user for 30 seconds, and concurrent evaluations for the same user coalesce into one call. See OpenFeature.
  • NexusProviderOptions - targeting_ttl, max_targeting_keys and addon_suppression, each validated when the provider is built.
  • find_flag on the blocking client, matching the async one: a disabled flag and an absent one are distinguishable on both surfaces.
  • Breaking: evaluate_ab takes &HashMap<String, String> for its attributes on both clients. The service compares attribute values with eq, neq and in, so a string map is what a cohort rule can act on. Values built with json!("pro") become "pro".to_string().
  • Through the provider, a whole number written 5.0 resolves as 5. JSON has one number type; a fractional value resolves as TYPE_MISMATCH with your default rather than being truncated, and values beyond the float range keep their exact value.
  • A composite config value containing a JSON null resolves as TYPE_MISMATCH. The OpenFeature value model has no null, so such a value cannot be represented there; read it as raw JSON through the wrapped client.

What’s new in v0.11.0-beta.2

The largest rework in the crate’s history. It breaks the public API; Async migration lists the one-line change per break.
  • Async-first client. create, sync, set_secret, delete_secret, delete_secret_version and evaluate_ab are async fn. Cache reads stay synchronous, and spawn_blocking wrappers are no longer needed.
  • blocking feature for applications with no runtime of their own.
  • tracing instrumentation with structured fields on create, sync, the token exchange and the stream loop.
  • Owner-only file-type secrets. Each client materialises them into its own private 0700 directory, and each file is created 0600 at creation via create_new + O_NOFOLLOW plus an atomic rename. Two clients never share a path, and a secret removed on the server is removed from disk.
  • Cleanup runs while the stream is active. The SSE task now holds only a weak reference, so dropping the last clone reaches the cleanup.
  • Stream deadlines - a connect deadline plus an idle deadline that resets on every byte, keepalive comments included.
  • One status-to-error mapping shared by every endpoint; evaluate_ab reports RateLimited on 429.
  • Bounded response bodies everywhere, with a size error instead of a truncated document.
  • Coalesced refreshes - concurrent reads on a stale snapshot trigger one request, and snapshots cannot apply out of order.
  • Billing back-off instead of a halt, cleared by the next successful sync.
  • Configuration validated once, at construction, naming the option and the list index.
  • auth_expiring forces a refresh, and a 401 forces one refresh plus one retry.
  • NexusError::Transport replaces Http, so the HTTP client is no longer part of the semver contract; the enum is #[non_exhaustive] and gained Config and ResponseTooLarge.
  • Exact RFC 3339 date arithmetic, so a quarantine expiry between March and December of a leap year is no longer a day early, and an absurd expiry is clamped to 24 hours.
  • OpenFeature provider - see OpenFeature.
  • Edition 2024, thiserror 2, and minimum supported Rust version 1.88, measured and verified by a CI job.

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 reads “cannot read or write secrets with a public key”.

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, off by default. See Workload identity.
  • 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.
  • Security hardening - plain-http endpoints rejected (loopback excepted); a failed WIF refresh fails closed; token-exchange 400/403 map to BadRequest/Forbidden; the slug Host header is sent on the exchange; metadata and exchange reads are bounded; expires_in is clamped.

What’s new in v0.8.0-beta.2

  • WIF GCP fix - the gcp provider 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.5.1-beta.1

  • Security - response bodies are no longer embedded in error messages; SecretNotFound truncates the key to 128 characters; file-secret paths carry an opaque hash rather than the key name; WIF token files are whitespace-trimmed.
  • SSE - flag.toggled triggers a re-sync, and a 429 carrying a quarantine body pauses reconnects until expires_at.

Latest release

v0.14.0-beta.2 on crates.io. The crate is on the beta track: the public surface is settling release by release, and graduating to stable is a decision to take once it has held still for one.

Documentation

Installation

Add the crate, pick your features, and check the Rust version floor.

Async migration

One line per break when moving from v0.10.x.

Configuration

Every option, its default, and what is rejected at construction.

API reference

Every method, with the errors it can return.

Caching behaviour

TTL, ETag, coalesced refreshes, and cleanup.

SSE live updates

Deadlines, reconnection, and the control events.

Workload identity

Keyless authentication on Kubernetes, AWS, GCP and Azure.

OpenFeature

The provider crate and its resolution mapping.