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

What’s new in v0.16.0

  • A custom logger whose method raises no longer fails an SDK operation. Every internal log call is contained, so a logging sink that raises - a full disk, a down syslog target - is dropped and the read, refresh, or create() (sync and async) that logged continues. The stream observer already had this guarantee; it now covers the logger too. The WIF credential source is deliberately not contained - it is on the auth path and still surfaces its error.

What’s new in v0.15.0

  • The async client has the write API. AsyncNexusClient gains set_secret, delete_secret and delete_secret_version, mirroring NexusClient; both route every write status through one shared path so they cannot drift.
  • The public-key guard reads the backend’s key_type, not just the key prefix - a key the server reports as public is refused secrets even without the wxp_ prefix, because either signal is enough.
  • follow_redirects is off on every HTTP client and the SSE line reader is bounded, so a credential-bearing request never follows a server-chosen redirect and a server that never emits a newline cannot make the client buffer without limit.
  • The async client keeps blocking file I/O off the event loop - file-secret writes and cleanup run in a worker thread.
  • Thread safety and the free-threaded (no-GIL) position are documented.
  • Changed: minimum httpx is now >=0.26 (0.25 does not import on Python 3.14).

What’s new in v0.14.0

  • The WIF provider set is a type. WIFProvider is a StrEnum unioned with the equivalent Literal, so the enum member and the plain string both type-check and a value outside the set does not. Members are strings, so nothing changes at runtime; an invalid one raises ValueError at WIFConfig(...).
  • exchange_payload builds the whole token-exchange body from an ExchangeContext, so a credential that is not an OIDC token can be expressed - and the aws_iam shape is reachable without botocore if you sign the request yourself.
  • A developer provider. After westyx dev setup, WIFConfig(enabled=True) authenticates a developer machine against a WIF-enforced service with the session the CLI already obtained - no token exchange, nothing to install. It is the last provider auto considers.
  • The API key and the session token stay out of __repr__, which is what a traceback rendered with frame locals prints.
  • Breaking: WIFConfig is keyword-only, and provider="aws_iam" with token_source is refused.

What’s new in v0.13.0

  • File-type secrets live in a per-client private directory, created 0700 lazily on the first file-type secret; every file inside is created 0600 with O_EXCL, so the mode is a guarantee regardless of what already occupies the path. A process-level atexit hook removes the files even when the process exits without close(). See File-type secret security.
  • A 402 Payment Required throttles the background refresh to one attempt every five minutes instead of ending it, and any successful sync - a 304 Not Modified included - clears billing_overdue. Settling the invoice restores service without a restart.
  • The SSE stream has an idle deadline - new stream_idle_timeout option, default 90 s, sized against the server’s 30 s keepalives. A connection reaped by a load balancer surfaces as a transport error and reconnects instead of blocking forever. See SSE live updates.
  • Breaking: ttl_seconds (and stream_idle_timeout) are validated at create() - zero, negatives and bool raise ValueError naming the option instead of silently becoming the default.

What’s new in v0.12.0

  • Per-user flag targeting through the OpenFeature provider. With a targeting key in the evaluation context, a boolean flag is resolved through the AB Testing add-on, so its rollout percentage and cohort rules apply to that identity. One request serves every flag the snapshot knows for that identity, results are memoised, and concurrent evaluations for one identity coalesce into a single request. Without a targeting key nothing changes.
  • find_flag(key) on both clients returns the flag’s is_active state or None when the flag is not in the cache at all - the distinction get_flag cannot express, and the one an OpenFeature provider needs in order to answer FLAG_NOT_FOUND.
  • NexusProviderOptions tunes the targeting TTL, the memoised-identity cap and the add-on suppression window; a value that cannot work is rejected at construction, naming the option.
  • Breaking: evaluate_ab refuses a non-string attribute value with TypeError naming the attribute, the provider no longer coerces numbers, and an unknown flag resolves as FLAG_NOT_FOUND.

What’s new in v0.11.0

A correctness and type-safety release. Nothing in the public API breaks.
  • Ships py.typed (PEP 561) for both packages. Without the marker, type checkers ignore an installed package’s annotations entirely - every SDK call resolved to Any in your project, however well annotated the SDK was. The SDK is now clean under both mypy --strict and pyright. See Type checking.
  • SSE reconnect fixes. A misconfigured sse_reconnect_cooldown used to kill the stream worker: the handler meant to fall back to the default schedule called a logger method that does not exist, and raised. The value is validated at create() now and rejected with a message naming the bad input. Separately, AsyncNexusClient ignored sse_reconnect_cooldown entirely and ended its stream permanently after three transient transport errors - it now reconnects on the configured schedule, matching NexusClient. See SSE live updates.
  • The SSE client now has a connect timeout. Lifting the read deadline on a long-lived stream is right; lifting the connect deadline with it was not, and a connect to a black-holed endpoint hung indefinitely with no error and no reconnect.
  • File-type secrets are written 0600, applied at creation rather than by a chmod afterwards, and opened with O_NOFOLLOW. Each client materialises to its own paths, so two clients holding the same secret never share a file. See File-type secret security.
  • A faulting stream observer is reported. Your observer still cannot break the SDK, but a callback that raises is logged with the hook name and the original exception instead of vanishing.
  • No assert in shipped code - python -O strips them, and the session-refresh precondition guard went with them.
  • CI gates on ruff, mypy, pyright and bandit, and the suite runs on Python 3.11 through 3.14 - every version this package advertises.

What’s new in v0.10.0

  • Version alignment across the Westyx Nexus SDK suite.

What’s new in v0.9.0

  • 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 base-URL host - a captured request is valid for that one service only, and there is nothing to configure. Requires the optional botocore dependency (pip install 'westyx-nexus-sdk[aws-iam]'). See Workload identity.
  • Azure Workload Identity (AKS) - the azure provider now prefers the projected federated token file ($AZURE_FEDERATED_TOKEN_FILE) before falling back to IMDS; auto-detection probes the file too.
  • Probe-based auto-detection - auto-detect now stats the Kubernetes / AWS-IRSA / Azure token files and live-probes the GCP and Azure metadata servers (~1 s timeout), instead of keying on environment variables absent on real cloud nodes.
  • Security hardening - both clients reject plain-http base_urls (loopback excepted); the Azure IMDS path refuses the generic default audience (must be api://<client-id>); the async client no longer blocks the event loop on metadata calls; the httpx.Client leak is fixed; metadata/exchange reads are bounded.

What’s new in v0.8.0

  • OpenFeature provider - new westyx-nexus-openfeature sub-package ships NexusProvider, an AbstractProvider for the OpenFeature Python SDK. Wraps an existing NexusClient; booleans via get_flag, string/integer/float/object via get_config. See OpenFeature provider.

What’s new in v0.5.1

  • Requires Python 3.11+ - Python 3.10 is EOL; minimum is now 3.11.
  • Security improvements - exception messages contain only status codes; file-type secret paths are fully hashed; WIF tokens stripped of whitespace on all providers.
  • WIF reliability - session refreshes before each SSE reconnect; expired sessions no longer cause permanent TTL-polling fallback.
  • CI - tests run on merge requests; publish restricted to main-branch tags.

What’s new in v0.5.0

  • Write API - set_secret, delete_secret, delete_secret_version for programmatic secret management. secret keys only; public keys raise NexusPublicKeyError immediately without a network call.
  • NexusRateLimitedError - new error for HTTP 429 on write endpoints.

What’s new in v0.4.0

  • Path prefix change - all API paths are now /v1/ (previously /api/v1/). Update base_url to use <slug>.westyx.dev.
  • NexusQuarantinedError - new typed error raised on 429 with quarantine body. Both sync and stream paths detect this.
  • on_quarantined(reason, expires_at) observer callback - StreamObserver gains a sixth callback; fires on quarantine events from both the stream and sync paths.
  • Quarantine backoff - stream sleeps until expires_at before reconnecting; background sync is paused during the quarantine window.
  • Removed ConfigEntry.is_public - the field is no longer populated.

Highlights

  • Python 3.11+ - single runtime dependency (httpx); the optional aws_iam WIF provider adds botocore via the [aws-iam] extra
  • Both sync and async APIs - NexusClient and AsyncNexusClient share the same cache + SSE protocol; only the I/O model differs
  • Optional framework adapters - Django, FastAPI, Flask integrations via extras (pip install "westyx-nexus-sdk[django]")
  • Thread-safe TTL cache with atomic snapshot replacement and ETag/304 support
  • SSE live updates - propagates remote changes within milliseconds; falls back to TTL polling after 3 transport errors
  • Typed error hierarchy - NexusError base + 13 subclasses for isinstance / except matching
  • Workload Identity Federation (v0.2.0) - Kubernetes / AWS IRSA / GCP / Azure auto-detection; bearer JWT auth; AWS IAM (aws_iam) for ECS/Fargate/Lambda/plain-EC2 (v0.9.0)
  • Stream observer hooks (v0.2.0) - structured callbacks for SSE lifecycle events
  • AB Testing (v0.3.0) - evaluate_ab for batch per-user flag evaluation
  • File-type secrets (v0.3.0) - get_secret_file_path materialises type: "file" secrets to temp files
  • OpenFeature provider (v0.8.0) - NexusProvider sub-package (westyx-nexus-openfeature) for the OpenFeature Python SDK
  • Fully typed (v0.11.0) - ships py.typed; clean under mypy --strict and pyright

Package

Hosted on the GitLab PyPI Package Registry. Install:
Latest release: v0.16.0 (2026-08-27 - a consumer logger that raises can no longer take down an SDK operation).

Pages