# Unreleased - **BREAKING: Node.js 18 support is dropped, as announced in 2.3.0.** `engines.node` is now `>= 20.19.0`. Node 18 reached end-of-life on 2025-04-30 and no longer receives security patches from the Node.js project; the runtime deprecation warning added in 2.3.0 (`checkNodeVersion.js` / `NodeVaultClientNode18Deprecation`) is removed along with it, since it has served its purpose. CI drops the Node 18 legs from the `test` and `e2e` matrices and moves the single-Node-version jobs (`audit`, `lint`, `coverage`, `package`, `e2e-kv2`) from Node 20 to Node 22; `.nvmrc` now pins 22. - **Added Node.js 26 (the current release line, on track to become the next LTS on 2026-10-28) to the `test` and `e2e` CI matrices.** Also flagging, not acting on: **Node 20 itself reached its own documented end-of-life on 2026-04-30** (github.com/nodejs/Release schedule.json) — the same category of problem this release fixes for Node 18. `engines.node >= 20.19.0` keeps the commitment 2.3.0 already published, but does not by itself get consumers off an unsupported runtime; whether to raise the floor further (e.g. to Node 22, the oldest line still in Maintenance LTS) is a maintainer call the previous release didn't anticipate needing this soon, not something folded into this PR unasked. - **Added HashiCorp Vault 2.1.x to CI.** `e2e` gains a `{node: 22, vault: '2.1'}` leg alongside the existing `2.0` one (both Vault 2.x lines now on one Node version, matching the existing convention for the 2.x axis); `e2e-kv2` now runs against all three supported lines (`1.21`, `2.0`, `2.1`). `docker-compose.yml`'s reproduce-locally comment gained the matching `VAULT_IMAGE=hashicorp/vault:2.1` example. - **Dependency updates, unblocked by dropping Node 18** (previously held back in `.github/dependabot.yml` purely because their majors require Node >= 20): `mocha` 11.7.6 → 12.0.0, `eslint` 9.39.5 → 10.10.0, `@eslint/js` 9.39.5 → 10.0.1, `c8` 10.1.3 → 12.0.0. Also `@aws-sdk/credential-providers` 3.1100.0 → 3.1130.0 (a routine in-range bump). All devDependencies/tooling; nothing here ships to consumers. - **`peerDependencies.config` widened from `>=1 <4` to `>=1 <5`** (admits config 4.x; config 5.x is still excluded — see below). This surfaced a real, undocumented breaking change in config 4.x: `config.util.initParam`, which `VaultNodeConfig`'s `NODE_CONFIG_DIR` resolution depended on, was silently removed from the public API (`config.util` is now a `ConfigUtils` instance with no such method — config's own 4.0.0 release notes list three breaking changes and this isn't one of them). Fixed by replicating `initParam`'s exact historical behavior (`--NODE_CONFIG_DIR=value` command-line argument, then the environment variable, then the default) directly in `VaultNodeConfig.resolveConfigDir`, which no longer touches `config.util` at all — verified against config 1.31.0, 3.3.12 and 4.4.2. config 5.x remains ignored in `dependabot.yml`: it is a ground-up ESM rewrite ("node-config is now an ESM module" per its own release notes), which this CommonJS codebase's synchronous `require('config')` cannot adopt without its own dedicated compatibility work — raising that cap needs its own PR, not a bundled guess. - Security: raise the `brace-expansion` override from `^5.0.9` to `^5.0.12` (lock 5.0.9 → 5.0.12). Clears GHSA-6j4f-fj2g-mc7p and GHSA-qhr7-859c-m2p7 (high, stack exhaustion from uncontrolled recursion) and GHSA-q2hr-2g5m-vwhr (quadratic-time `{a},b}` rewrite), all published 2026-09-29 and fixed by 5.0.12. Dev/transitive only (eslint → minimatch); no runtime dependency or behavior change. # 2.3.0 Release notes (2026-09-11) - **This is the last release of node-vault-client to support Node.js 18.** Node 18 reached end-of-life on 2025-04-30 and no longer receives security patches from the Node.js project, independent of anything pinned in this package's own dependency tree — which is itself feeling the pressure: `c8`, `eslint`, `@eslint/js`, `config` and now `mocha` all have majors held back in `.github/dependabot.yml` purely because they drop Node 18. Requiring the client now emits a one-time `process.emitWarning` (code `NodeVaultClientNode18Deprecation`) when running under Node 18, so consumers who never read a changelog still see it. The next major release raises `engines.node` to `>= 20.19.0`, drops the Node 18 CI matrix legs, and clears the accumulated ignore-list entries so those dependencies resume normal updates. No other behaviour changes; this is purely a deprecation notice ahead of that release. - Added optional `distributedClaimAccessToken` and `distributedClaimAccessTokenProvider` keys to the `jwt` backend's `config` (#175), which supply Vault's optional `distributed_claim_access_token` login parameter. It matters only for Microsoft Entra ID (Azure AD): past 200 groups Azure stops putting group membership in the token and sends OIDC distributed claims instead — `_claim_names`/`_claim_sources` pointing at the Microsoft Graph API — and a mount whose `provider_config` sets `fetch_groups` skips the claim unconditionally and always asks Graph. Either way Vault has to call Graph itself, and the JWT being logged in with is not a credential for that call, so without this parameter such a login fails at the group-fetch step — after the JWT has already validated, so the failure names the group lookup rather than the token, which was fine. `distributedClaimAccessToken` takes a literal Graph access token; it is fixed at construction and re-sent on every re-login, so it inherits the literal-`jwt` staleness caveat — more sharply, since an Entra access token lasts about an hour. `distributedClaimAccessTokenProvider` takes an (optionally async) function invoked fresh at login time — never at construction, never cached — exactly mirroring `jwtProvider`, and is the option for anything longer-lived than the Graph token. Providing both raises `InvalidArgumentsError` at construction, as does a non-function provider; a provider resolving to a non-string or empty string raises it at login, without a request being sent. Purely additive: both keys are optional and absent by default, and with neither set the login request body is byte-for-byte what it was before, so no existing configuration changes behaviour. The README's JWT section gains a subsection on when this is needed, and records that `fetch_groups` is a `provider_config` option on the auth mount's config rather than on the role, while `groups_claim` — without which Vault resolves no groups and ignores any Graph token passed — is on the role. - Documented the `bound_audiences` requirement for JWT auth, which is the most common reason a first login fails and was previously absent from the README. Vault requires a `jwt` role to bind the audience the token carries, but does not catch the omission when the role is created: as long as the role has some other bound constraint it is accepted, and the failure only appears at login as `audience claim found in JWT but no audiences bound to the role`. The JWT section now gives that error verbatim, the wrong-audience variant, and a `vault write .../role/...` example that binds the audience. The GitHub Actions section additionally spells out that `core.getIDToken('vault')` mints `aud: vault`, so the role must bind `vault` — following that snippet without it was a guaranteed failed login. Also recorded that Vault does not require an `exp` claim, so a `jwtProvider` that omits one produces a credential that never expires. Every quoted error string was taken from a live Vault and is identical on 1.21 and 2.0. No code change. # 2.2.0 Release notes (2026-09-01) - Documented three things about the HTTP transport that were true but unwritten, and scoped the `version` npm hook. No runtime change. `api.requestOptions` now carries a note that the `undici` you install has to be interface-compatible with the one Node bundles: on Node 24 a dispatcher from `undici@8` is rejected by the global `fetch()` with `cause.code` of `invalid onRequestStart method` before the request leaves the process, so the proxy and self-signed-CA recipes need `undici@^7`. A new "Request timeouts" section records that there is no default timeout — a Vault that accepts the connection and never answers leaves calls pending indefinitely — and gives the dispatcher-based fix, plus why a single `signal: AbortSignal.timeout(ms)` in `requestOptions` is the wrong tool: it is shared by every request, so it works once and then aborts the rest. A new "Redirects and the Vault token" section records that requests follow redirects (Vault HA answers standbys with a 307 to the active node) and that Node's `fetch()` forwards `X-Vault-Token` across a cross-origin redirect, since it strips only `Authorization`, `Cookie` and `Proxy-Authorization` — so `api.url`, its DNS and any load balancer in front of it are trusted infrastructure. Finally, the `version` hook was `git add -A .`, which swept any unrelated working-tree change into the release commit; it now stages only `CHANGELOG.md`, `package.json` and `package-lock.json`. - `VaultClient.boot()` now logs a warning when it is called for a name that already exists with options that differ from the ones the instance was booted with (#146). The options were, and still are, ignored in that case — the memoized instance is returned unchanged — so this only makes a silent mismatch visible. Silent when the options match (compared order-insensitively, as a hash, so no credential is retained for the comparison) and when `logger: false`. - Fixed renewal callbacks acting on state they no longer own (#145). A renewal request still in flight when its token was replaced, or when `close()` / `cancelTokenRefresh()` was called, would apply its result anyway: overwriting the newer token, clearing the newer token's timer and then bailing on its own expired one (leaving a live token permanently un-renewed), or re-arming a timer after the client had been closed. Superseded callbacks are now discarded. Renewal that is not superseded behaves exactly as before. - Added `auth.renewal: false`, which disables the background token-renewal timer (#17). The client then uses the token until it expires and re-authenticates on the next call instead of renewing it in the background. Useful for short-lived processes — the renewal timer keeps the Node.js event loop alive, so without it a finished script does not exit unless you call `close()` — and wherever re-login is preferable to extending a lease. Default behaviour is unchanged. Note this is only a no-op for backends that can obtain a fresh credential on their own (`kubernetes`, `iam`, `jwt` via `jwtPath`/`jwtProvider`): `token` auth cannot re-authenticate at all and will raise `AuthTokenExpiredError` once the token expires, and `appRole`/literal-`jwt` replay the same credential. Expiring a token also revokes the leases it created, which matters if you read dynamic secrets. - Added `auth.renewalFraction` and `auth.renewalIncrement`, for tuning renewal rather than turning it off (#17). `renewalFraction` (default `0.5`, range `(0, 1)`) sets how much of the token's remaining lifetime to wait before renewing; a lower value renews earlier and leaves room for more retries, which shrink geometrically as the lifetime does. `renewalIncrement` (unset by default) is sent as `increment` to `auth/token/renew-self` to request a specific extra TTL, which Vault caps at the token's max TTL. Both are validated at construction and raise `InvalidArgumentsError` on bad input. Defaults reproduce the previous behaviour exactly: the halfway point, and a renew request with a `null` body. All three keys live on `auth`, not in `auth.config`, so they cannot collide with a key an existing caller already passes to a backend; no constructor signature changed either, so anything subclassing `VaultBaseAuth` is unaffected. - Added first-party TypeScript declarations (`index.d.ts`), referenced by the `types` field and included in the published `files` (#159). The package previously shipped none, leaving TypeScript consumers on the third-party `@types/node-vault-client`, which stops at the 1.x API: it has no `jwt` backend, no `close()`, no `delete()`/`update()`/`request()`, none of the KV v2 version or metadata methods, none of the `api.namespace`/`api.kv`/`api.engines`/ `api.requestOptions` or renewal options, and it declares `AuthToken`, `Lease` and the other sibling classes as runtime exports of the entry point even though it exports only the `VaultClient` class — so `new VaultClient.Lease(...)` type-checked and then threw. `auth` is typed as a discriminated union on `type`, and the three mutually-exclusive JWT sources are enforced at compile time. Types that appear in signatures are exposed in type space under the `VaultClient` namespace. Declarations are verified by `npm run test:types` in CI, which compiles positive usage together with `@ts-expect-error` cases so a wrong signature fails the build. `src/errors.d.ts` covers the error classes, which the README documents as `node-vault-client/src/errors` because the entry point does not export them; that import previously raised `TS7016` under `strict`, so the documented path was the one TypeScript rejected. The declarations are deliberately permissive wherever the runtime tolerates more than the JSDoc suggests, so that no usage which compiled against the third-party types and works at runtime is newly rejected: a partial `logger` object is accepted (missing methods fall back to `console`, as before), and the methods returning a Vault response body stay assignable to `Promise`. Runtime behaviour is unchanged; no file under `src/` was touched. If you have `@types/node-vault-client` installed, uninstall it. - Added a JWT auth backend (`auth.type: 'jwt'`, default mount `"jwt"`) for workload identity federation — GitHub Actions, other CI systems, GCP/Azure/SPIFFE workloads — against Vault's [JWT auth method](https://developer.hashicorp.com/vault/docs/auth/jwt). Models `VaultKubernetesAuth`. `config.role` is optional, matching Vault's `default_role` fallback. Exactly one of three mutually-exclusive sources supplies the JWT: a literal `config.jwt` string (CI jobs / processes shorter-lived than the token — a re-login resends that same string, so it fails once the IdP-issued token itself expires); `config.jwtPath`, a file re-read on every login (rotated projected tokens); or `config.jwtProvider`, an (optionally async) function invoked fresh at login time — never at construction, never cached — for tokens minted per login such as GitHub Actions' `core.getIDToken()` or a cloud metadata endpoint. A `jwtProvider` resolving a non-string/empty string, or a non-function `jwtProvider`, fails fast with `InvalidArgumentsError` without sending a login request. Only the non-interactive `jwt` flow is implemented; the browser-redirect `oidc` flow is out of scope for this service client. See the README's "JWT auth" section. - Documented how to import the error classes (#161). The README named `UnsupportedOperationError` in eight places and `VaultError` in the error table, but nothing in the repository showed a consumer how to obtain either: the only `require` of the errors module was the example app's in-tree relative path. The `Error classes` section now gives the `node-vault-client/src/errors` import with a worked `instanceof` example, and the table lists all six exported classes with what raises each; it previously listed two. Two tests guard it: one fails if `files` would stop publishing `src/errors.js`, and one fails if a class is exported but missing from the README table. No runtime change, and no `exports` field was added, so every existing deep import keeps working. # 2.1.2 Release notes (2026-08-03) - Internal refactor: `VaultBaseAuth` no longer overloads a single `__authToken` field with two types. The in-flight login now lives in `__pendingLogin` (`Promise|null`) and the resolved token in `__authToken` (`AuthToken|null`), so `getAuthToken()` reads the auth state directly instead of discriminating with `instanceof` at each use site. No behavior change — the single-flight login (concurrent callers share one login) and the renewal-timer wiring are unchanged, and both are now pinned by tests. Closes #120. # 2.1.1 Release notes (2026-07-31) - Dependencies bumped, with **zero known vulnerabilities and Node 18 still working**. The selection rule is deliberately "newest version that still *runs* on Node 18", not "newest version whose `engines` field mentions Node 18" — for most packages the `engines` bump to Node 20 is policy rather than a technical requirement, and capping on the declaration alone would force downgrades below patched releases. `npm audit` reports 0 vulnerabilities, as it did on 2.1.0; note that capping purely on `engines` declarations was tried first and produced 26 advisories (1 critical, 7 high, 18 moderate), because every patched release of `@aws-sdk/credential-providers`, `serialize-javascript` and `brace-expansion` requires Node 20+. That approach is preserved in the branch history for auditability. - Bumped to latest: `@aws-sdk/credential-providers` → `^3.1100.0`, `aws4` `^1.8.0` → `^1.13.2`, `chai` → `^6.2.2`, `globals` → `^17.8.0`, `lodash` → `^4.18.1`, `sinon` → `^22.1.0`, `sinon-chai` → `^4.0.1`, `eslint`/`@eslint/js` → `^9.39.5`. Security overrides stay on their patched releases: `serialize-javascript` `^7.0.7`, `brace-expansion` `^5.0.9`. - Held below latest, because these genuinely break on Node 18 rather than merely declaring against it: `c8` stays `^10.1.3` (11+ requires Node `20 || >=22`; 12 pulls an ESM-only `yargs` and dies with `ERR_REQUIRE_ESM` on Node 18 — as a side effect `npm run coverage` now works on Node 18, which it did not on 2.1.0), `eslint` stays on 9.x (10.x declares `^20.19.0 || ^22.13.0 || >=24`), and the `config` peer range stays `<4` (config 4 requires Node `>=20`). - `npm ci` on Node 18 prints 19 `EBADENGINE` warnings — 16 AWS SDK/smithy packages plus `brace-expansion@5.0.9`, `lru-cache@11.5.2` and `serialize-javascript@7.0.7`. Each was executed on Node 18 to confirm the warnings are cosmetic: the AWS SDK resolves a provider chain and signs a request, and `brace-expansion`, `lru-cache`, `glob` and `minimatch` all behave correctly. - Verified on Node 18.20.8 / 20.20.2 / 22.23.2 / 24.18.1, each against a **fresh Vault 1.13.3 instance in Docker**: `npm ci`, 306 unit tests, `lint`, the c8 threshold gate, and both e2e suites (`test:e2e` 6 passing/1 pending, `test:e2e:kv2` 10 passing) pass on all four. - Two known limitations on Node 18, both pre-existing on 2.1.0 and neither hit by any npm script or CI job. Documented here so they are not rediscovered as mysteries: - `mocha --parallel` does not work on Node 18. `serialize-javascript@7.x` calls `crypto.getRandomValues` on the global at module load, and Node 18 has no unflagged global `crypto`, so mocha's parallel worker (`lib/nodejs/worker.js`) throws `ReferenceError: crypto is not defined` — surfaced unhelpfully as `✖ ERROR: null`. None of the `test*` scripts use `--parallel`; serial runs never load that module. Downgrading the override to `^6.0.2` restores parallel mode on Node 18 but reinstates a high advisory (GHSA-5c6j-r48x-rmvq RCE via `RegExp.flags`, GHSA-qj8w-gfj5-8c6v CPU-exhaustion DoS), so the patched version is kept. - Brace glob patterns (`*.{js,mjs}`) throw `TypeError: expand is not a function` under the `brace-expansion` override. v5 changed the export from a default function to a named `{ expand }`, and the blanket override applies it to `minimatch@3.1.5` (via `eslint`, wants `^1.1.7`) and `minimatch@9.0.9` (via `mocha`, wants `^2.0.2`), which still call it as a function. Brace-free patterns are unaffected, and neither `eslint.config.js` nor any test glob uses braces. Scoping the override per-major is not a way out: the backported `1.1.16`/`2.1.2` releases clear GHSA-3jxr-9vmj-r5cp but are still flagged high by GHSA-mh99-v99m-4gvg (unbounded-expansion OOM), which is only fixed in 5.0.8+. # 2.1.0 Release notes (2026-07-28) - Security: pin patched transitive tooling via `overrides` — `brace-expansion` to `^5.0.8` (clears GHSA-3jxr-9vmj-r5cp, Dependabot #60, and GHSA-mh99-v99m-4gvg) and `js-yaml` to `^4.3.0` (clears the concurrent quadratic-CPU merge-key advisory). Dev/transitive only (eslint, mocha, glob, c8) — no runtime dependency or behavior change; `npm audit --audit-level=high` is clean. - Perf: `MountResolver` no longer re-sorts the `api.engines` override map on every `resolve()` — entries are normalized and sorted once at construction (the map is now snapshotted: mutating the object after `VaultClient` construction no longer affects resolution). The mount cache is now a bounded LRU (default 500 entries, `opts.maxCacheSize`) probed by segment-boundary prefix in O(path depth) instead of a linear scan over every cached mount, so long-lived services against many/dynamic mounts get bounded memory and lookup cost. Measured at 200k worst-case resolves: engines lookup 1191ms → 34ms (50 entries), cache lookup 1019ms → 149ms (500 mounts). Also adds test coverage for the previously untested empty-detection-response error. Closes #108. - Internal refactor: unify the copy-pasted request pipeline in `VaultClient`. `update()`, the raw `request()`, and the KV v2-only helpers now delegate to the single `__resolveAndRequest` entry point (one `resolver.resolve()` call site instead of three). No behavior change — the pipeline is locked by new characterization tests across v1/v2 mounts, namespaces, and extra headers. Closes #110. - Non-2xx Vault responses are now rejected with a typed `VaultHttpError` (part of the `VaultError` hierarchy, exported from the errors module), so callers can `instanceof`-check HTTP failures. Backward compatible: the message (`" - "`) and the `statusCode`/`error` properties are unchanged, and the thrown value is still an `instanceof Error`. - Auth backends now fail fast with `InvalidArgumentsError` when a required config field is missing: `role_id` for AppRole, `role` for IAM and Kubernetes (previously only Token auth validated its input, and a missing/empty config surfaced later as an unhelpful login failure or `TypeError`). Valid configurations behave exactly as before. # 2.0.4 Release notes (2026-07-02) - CI: make the quality gates actually enforce. `c8` now runs with `check-coverage` and per-metric thresholds (statements/branches/functions/lines) pinned just below the current measured coverage, so a coverage regression fails the `coverage` job instead of silently passing. Linting now covers `test/` in addition to `src/` (`eslint src/ test/`), catching stray unused imports/vars in the ~19 test files that were previously unchecked. The `npm audit --audit-level=high` choice is now documented in the workflow. No runtime behavior change. - `VaultError` now accepts the standard `{ cause }` option (`new VaultError(msg, { cause })`) and exposes it as `error.cause`, so wrapped/underlying errors can be chained. Backward compatible — omitting the option leaves `cause` undefined. # 2.0.3 Release notes (2026-07-02) - Fix (behavior change): apply `X-Vault-Namespace` to **every** request. The header was previously built independently by the AppRole and IAM backends and by `VaultClient` for KV operations, but was **missing from token lookup/renewal (`/auth/token/lookup-self`, `/auth/token/renew-self`) for all backends, and from Kubernetes login entirely**. Against a namespaced Vault this silently sent those requests to the **root** namespace, so Token and Kubernetes auth were effectively broken with namespaces. The namespace is now injected in a single place — `VaultApiClient` — so login, lookup, renewal, and secret operations all inherit it for every auth backend. `Token` and `Kubernetes` gain namespace support as a result. `api.namespace` is now the canonical config location; `auth.config.namespace` continues to work. If you relied on the previous (buggy) behavior where lookup/renewal hit the root namespace, this changes which namespace those calls target. Closes #106. # 2.0.2 Release notes (2026-07-02) - Security: stop logging the raw Vault `client_token` at debug level. The AppRole (`VaultAppRoleAuth`) and AWS IAM (`VaultIAMAuth`) backends logged `auth.client_token` verbatim on every successful login, and `VaultBaseAuth` logged the raw token id when arming the renewal timer. With a custom debug logger wired up — exactly what the README recommends — this wrote a replayable Vault token into durable logs on every authentication. These sites now log the non-sensitive token `accessor` instead. This completes the same class of fix shipped for the Kubernetes backend and response bodies in 2.0.1. Closes #104. # 2.0.1 Release notes (2026-06-16) - Security: stop logging secrets at debug level. The Kubernetes auth backend no longer logs the service-account JWT or the issued Vault client token, and `VaultApiClient` no longer logs full response bodies (which carry auth tokens and secret reads). Debug logs now record only non-sensitive metadata — token paths, request method/URI, and HTTP status codes. - Dependencies: drop four runtime dependencies. `bluebird` and `assign-deep` are replaced with native promises and `lodash`; `pretty-ms` and `url-join` are inlined as small helpers (their latest majors are ESM-only and cannot be used from this CommonJS package). The `lodash` floor is raised to `^4.17.21`. Runtime dependencies are now `@aws-sdk/credential-providers`, `aws4`, `lodash`, and `long-timeout`. - Reject malformed substitution values whose path or key is empty (e.g. `#value` or `path#`) with `InvalidArgumentsError`, instead of failing later with a less clear error. # 2.0.0 Release notes (2026-06-12) - Fix a process that never exits after reading with a renewable token. The background token-refresh timer (`long-timeout`) kept the Node.js event loop alive with no way to stop it. Add `VaultClient#close()` (and `VaultBaseAuth#cancelTokenRefresh()`) to cancel the timer so short-lived scripts can exit; `VaultClient.clear()` now also closes the instances it removes. Default behavior is unchanged — long-running servers keep renewing as before. Closes #31. - IAM auth: add an optional `region` config option. When set, the STS `GetCallerIdentity` request is signed against the regional endpoint (`sts..amazonaws.com`) and the SigV4 credential scope is bound to that region, with the signed Host header and `iam_request_url` kept consistent. Fixes `SignatureDoesNotMatch — Credential should be scoped to a valid region` on non-`us-east-1` STS endpoints. Omitting `region` preserves the previous global-endpoint behavior. Closes #25. - Add `api.requestOptions`, shallow-merged into every underlying `fetch()` request. Enables routing traffic through a proxy/SOCKS agent and trusting a self-signed / internal-CA Vault by passing an undici `dispatcher`. Closes #37 and #29. - Replace the deprecated `request`/`request-promise` HTTP libraries with Node's native `fetch`. Removes the `request` runtime dependency and clears the associated Dependabot/deprecation alerts; this is the foundation for the new `api.requestOptions` (undici dispatcher) support. Closes #59. - [BREAKING] Minimum supported Node.js is now 18.0.0 (was 14.0.0); the client relies on native `fetch`. Note: on some Node.js 18.x environments, `fetch` may be treated as experimental and require `--experimental-fetch`; use a newer Node.js version for fully nonexperimental `fetch` behavior. - Auth token: derive expiry from Vault's authoritative `expire_time` (RFC3339), falling back to `ttl` only when absent. Closes #51. - Raise `AuthTokenExpiredError` for expired non-refreshable tokens instead of silently using a stale token. Closes #50. - Replace deprecated `new Buffer()` with `Buffer.from()` in IAM auth STS body encoding. Closes #52. # 1.0.0 Release notes (2023-08-02) - `aws-sdk` is no longer a peer dependency - [BREAKING] From now on the minimum supported version of Node.js is 14.0.0. - [BREAKING] Changes in IAM configuration. If you explicitly passed aws-sdk@2 credentials to `VaultClient.boot` like below: ```js const vaultClient = VaultClient.boot('main', { api: {url: 'https://vault.example.com:8200/'}, auth: { type: 'iam', mount: 'example', config: { iam_server_id_header_value: 'example', role: 'example', credentials: AWS.CredentialProviderChain.defaultProviders // <-- this line } }, }); ``` This will no longer work. You need to either: - Do not pass the credentials at all and rely on the credentials auto-discovery ```js const vaultClient = VaultClient.boot('main', { api: {url: 'https://vault.example.com:8200/'}, auth: { type: 'iam', mount: 'example', config: { iam_server_id_header_value: 'example', role: 'example', } }, }); ``` [OR] - Pass the credentials explicitly in the following format ```js const vaultClient = VaultClient.boot('main', { api: {url: 'https://vault.example.com:8200/'}, auth: { type: 'iam', mount: 'example', config: { iam_server_id_header_value: 'example', role: 'example', credentials: { accessKeyId: 'AWS_ACCESS_KEY', secretAccessKey: 'AWS_SECRET_KEY', } } }, }); ```