NexusClient bean at startup, performs a blocking initial sync, and starts the SSE stream in a daemon thread.
What’s new in v0.15.0
- The secret guard honours the backend’s key classification. A key is treated as public - and secret access refused - when either the configured key’s prefix or the server’s
key_typesays so, andgetKeyType()reports that effective type. A public key issued without thewxp_prefix can no longer reachgetSecret. See Workload identity. - A logger that throws cannot take the client down. Every internal log call is contained, so a failing logging sink never propagates into
create(), a read, or the stream thread. The stream observer already had this guarantee. See Stream observer. - The cached snapshot never renders a secret. Its
toString()prints counts only, so logging a snapshot cannot leak a secret name or value.
What’s new in v0.14.0
- The WIF provider is a type.
WIFProvideris an enum, so the resolver’s dispatch is compiler-checked andnexus.wif.providerbinds leniently, fails the start with the valid values on an unknown one, and offers completion inapplication.yml. WIFConfighas a factory per provider, so a provider’s options are reachable only through the factory that owns them - a combination that has no meaning cannot be written down.WIFConfig.custom(...)builds the whole token-exchange body, which is what lets a credential the SDK has no provider for be expressed at all.- A
developerprovider. Afterwestyx dev setup, a developer machine authenticates with the session the CLI already obtained - no token exchange, nothing to install. Always the last providerautoconsiders. - The API key stays masked on the actuator’s configuration endpoints even with
show-valueson.
What’s new in v0.13.0
- 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 Modifiedincluded - clearsisBillingOverdue(). Settling the invoice restores service without a restart. A server-supplied quarantineexpires_atis clamped to 24 hours. See Error handling. - Breaking: configuration is validated at
create(), never coerced. A zero or negativettl, an emptysseReconnectCooldownor an entry below one minute raisesNexusConfigExceptionnaming the option instead of silently becoming a default; a bad value bound throughapplication.propertiesfails the context start with the option name in the log. See Configuration. - Breaking: the OpenFeature provider carries an integer larger than the
Valueinteger slot as its exact decimal text inside an object or array resolution; the scalar integer resolution still answersTYPE_MISMATCHfor the same value on purpose. See OpenFeature.
What’s new in v0.12.0
- Per-user targeting in the OpenFeature provider - a boolean evaluation whose
EvaluationContextcarries a targeting key is evaluated for that identity through the AB Testing add-on and reportsTARGETING_MATCH. One request covers every flag in the snapshot, the results are memoised per identity, and concurrent evaluations for one identity coalesce into a single call. See OpenFeature. findFlag(String)returnsOptional<Boolean>, so a flag that does not exist is distinguishable from one that exists and is off. See API reference.- An object config resolves into the OpenFeature value model, not into JSON text, so
asStructure()andasList()work on it - nested objects and arrays included. - Integer resolutions are exact - a fractional value, or one outside
intrange, reportsTYPE_MISMATCHinstead of being narrowed to a wrong number. evaluateABtakesMap<String, String>attributes (breaking), matching what the endpoint binds; anullvalue is treated as unset.
What’s new in v0.11.0
- One artifact for Spring Boot 3.5, 4.0 and 4.1. The starter is built against Spring Boot 4.0 - the oldest line still receiving open-source security patches, since all of 3.x left support on 2026-06-30 - and every pipeline run tests it against 3.5.16, 4.0.7 and 4.1.0. There is no
-boot3/-boot4split and no framework version in the coordinates. - The SDK no longer picks a JSON library for you. Jackson 2 (
com.fasterxml.jackson, what Spring Boot 3 ships) and Jackson 3 (tools.jackson, what Spring Boot 4 ships) are both declared<optional>, and the SDK selects an adapter from the classpath at startup. Your application keeps exactly the Jackson it already had. See JSON values. - Config values are
JsonValue, not Jackson’sJsonNode(breaking).asText()becomesasString(),isTextual()becomesisString(), and absent lookups returnJsonValue.missing()instead ofnull.toJson()is there when you want to bind the value with your own mapper. NexusConfig.objectMapper(...)becomesjsonCodec(...)(breaking). Spring Boot applications need no change - the auto-configuration bridges your ownObjectMapperbean on either Jackson major, sogetConfigAsstill honours your modules and naming strategy.- File-type secrets are written
0600, owner-only, with the mode applied at creation rather than by a chmod afterwards, and openedCREATE_NEW+NOFOLLOW_LINKS. Each client materialises to its own paths, so two clients holding the same secret never share a file. - Java 17 remains the baseline - Spring Boot 4.1 requires only 17 and nothing here needs a newer API. CI additionally runs the suite on JDK 21.
- SpotBugs + find-sec-bugs run in the build, and the OpenFeature provider now has a CI test job.
- Dependencies current: SLF4J 2.0.18, AWS SDK for Java v2 2.49.4, OpenFeature SDK 1.21.0.
What’s new in v0.10.0
- Version alignment across the Westyx Nexus SDK suite.
What’s new in v0.9.0
aws_iamWIF 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 STSGetCallerIdentityrequest (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 signedX-Nexus-Server-IDis 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 optionalsoftware.amazon.awssdk:auth+:regionsdependencies. See Workload identity.- Azure Workload Identity (AKS) - the
azureprovider now prefers the projected federated token file ($AZURE_FEDERATED_TOKEN_FILE) before falling back to IMDS; auto-detection probes the file too, and the GCP identity request now includes&format=full. - 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); the metadata client disables redirects and the system proxy.
- Security hardening -
NexusClient.createrejects plain-http base URLs (loopback excepted); the Azure IMDS path refuses the generic default audience (must beapi://<client-id>); metadata/exchange reads are bounded; a non-positiveexpires_inis treated as an exchange failure.
What’s new in v0.8.0
- OpenFeature provider - new
nexus-openfeature-spring-bootsub-module. Wrap yourNexusClientin aNexusProviderand register it with the OpenFeature Java SDK. See OpenFeature.
What’s new in v0.6.0
- SSE reconnect after polling fallback - the SDK now re-attempts the SSE stream after falling
back to TTL polling.
sseReconnectCooldowncontrols the delay (clamped 1s-300s).
What’s new in v0.5.1
- Security improvements - exception messages contain only HTTP status codes; file-type secret paths are fully hashed; WIF tokens stripped of whitespace.
- WIF reliability - session refreshes before each SSE reconnect; expired sessions no longer cause permanent TTL-polling fallback.
- CI improvements - tests run on every MR and
mainpush; publish restricted tomain-branch tags.
What’s new in v0.5.0
- Write API -
setSecret,deleteSecret,deleteSecretVersionfor programmatic secret management. secret keys only; public keys throwNexusPublicKeyExceptionimmediately without a network call. NexusRateLimitedException- new exception for HTTP 429 on write endpoints.
What’s new in v0.4.0
- Path prefix corrected - all API calls now use
/v1/(e.g./v1/sync,/v1/stream). Updatenexus.base-urltohttps://<slug>.westyx.dev- no/apisuffix needed. - Quarantine support - HTTP 429 with
{"error":"quarantined","reason":"...","expires_at":"..."}body now throwsNexusQuarantinedException(sync) or triggers sleep-then-reconnect (stream).NexusStreamObserver.onQuarantined(reason, expiresAt)is called in both cases. isPublicremoved fromConfigEntry- the field is no longer present in sync responses.
What’s new in v0.3.1
Retry-After-aware SSE 429 handling - the stream now sleeps the indicated delay (clamped[5 s, 5 min]) and reconnects automatically when the server returns 429 with a parseableRetry-Afterheader. WithoutRetry-After, legacy terminate-on-429 + TTL polling fallback preserved.
What’s new in v0.2.0
- Workload Identity Federation - Kubernetes / AWS IRSA / GCP / Azure auto-detected; bearer-JWT auth with automatic refresh. Configure via
nexus.wif.*properties or aWIFConfigbean. - Stream observer hooks -
NexusStreamObserverinterface; the auto-configuration wires any bean automatically. - Service kind awareness -
getSecret()blocked withNexusServiceKindMismatchExceptiononkind=frontendservices. - 402 Payment Required handling -
NexusBillingException,isBillingOverdue(); background sync throttled to one attempt per five minutes, cache served, cleared by any successful sync. - Split sync vs stream
HttpClient- a short consumer timeout cannot truncate the SSE stream.
Highlights
- Java 17+ / Spring Boot 3.5, 4.0 and 4.1 - one artifact, tested against all three; auto-configured starter,
NexusClientbean from two properties - No JSON library forced on your application - whichever Jackson major your Spring Boot brings is the one the SDK uses (v0.11.0)
- Zero hard external dependencies beyond Jackson (already on the Spring Boot classpath) and SLF4J
- Thread-safe TTL cache with atomic snapshot replacement and ETag/304 support
- Background refresh - request threads are never blocked on cache expiry
- SSE live updates - propagates remote changes within milliseconds; falls back to TTL polling after 3 transport errors
- Typed exception hierarchy -
NexusExceptionbase + 10 subclasses forcatchclauses - 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
