Skip to content

chore: quality backlog from the 2026-07 audit (typed HTTP errors, config validation, untested paths, release hygiene)#119

Open
kurok wants to merge 1 commit into
masterfrom
chore/111-quality-backlog
Open

chore: quality backlog from the 2026-07 audit (typed HTTP errors, config validation, untested paths, release hygiene)#119
kurok wants to merge 1 commit into
masterfrom
chore/111-quality-backlog

Conversation

@kurok

@kurok kurok commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the actionable in-repo items from the 2026-07 audit quality backlog (#111): typed HTTP errors, fail-fast auth config validation, tests for the previously untested paths, and the in-repo release-hygiene items. Items that are already covered, blocked on another in-flight PR, or maintainer-decision-shaped are listed below and left open on the issue.

Refs #111

Issue checklist status

Untested paths

  • VaultKubernetesAuth fs.readFileSync throw path — new test asserts the fs error propagates and no login request is made
  • VaultIAMAuth default AWS credential-chain path — already covered by the existing "credentials from environment variables" test (constructs without explicit credentials, so fromNodeProviderChain() is built and resolved); no change needed
  • test/auth.base.test.mjs "reschedules when a renewal fails" — now asserts __refreshTimeout re-arms and that advancing the clock triggers a second renewal attempt
  • Prototype-pollution guard in VaultNodeConfig.deepMergedeepMerge is now exported for direct testing; tests cover __proto__/constructor/prototype skipping (via JSON.parse-created own keys), undefined-skip, in-place nested merge, and deep-cloning
  • Dedicated Lease.getMetadata() tests (present, fromResponse mapping, undefined for KV v1)
  • VaultApiClient non-2xx handling — tests assert err.error parsed-JSON contents, the non-JSON raw-text fallback, and the empty-body (undefined) case

Code quality

  • Typed HTTP errors — new VaultHttpError extends VaultError, thrown by VaultApiClient.makeRequest on non-2xx. Backward compatible: message stays "<status> - <text>", statusCode/error keep their shape, still instanceof Error
  • Config validation — InvalidArgumentsError on missing role_id (AppRole) / role (IAM, Kubernetes); Token auth now also handles a missing config object. Valid configs behave exactly as before
  • Skipped: VaultBaseAuth.__authToken promise/token two-field split — a "consider" refactor of the auth state machine with no behavior change; better done as its own focused change rather than bundled into this batch

Dependencies & release process

  • long-timeout — documented the decision to keep it (comment at the require site in VaultBaseAuth.js: unmaintained but tiny, dependency-free, and it works around the 32-bit setTimeout limit that real token TTLs exceed)
  • Release-time CHANGELOG check — the publish workflow now fails if CHANGELOG.md has no # <version> release-notes heading for the version being published
  • Skipped: structured logging / log-at-source in VaultApiClient — the issue says to do this after the catch/log/rethrow wrapper from Refactor: unify the 4x copy-pasted request pipeline in VaultClient #110, which is being handled in a separate in-flight PR

Changes

  • src/errors.js — add VaultHttpError (statusCode + error fields, legacy message shape)
  • src/VaultApiClient.js — throw VaultHttpError instead of an ad-hoc plain Error on non-2xx
  • src/auth/VaultAppRoleAuth.js, src/auth/VaultIAMAuth.js, src/auth/VaultKubernetesAuth.js — fail fast on missing required config; src/auth/VaultTokenAuth.js — null-safe config check
  • src/auth/VaultBaseAuth.js — document the long-timeout keep decision
  • src/VaultNodeConfig.js — export deepMerge so the security guard is directly testable
  • .github/workflows/publish.yml — release-time CHANGELOG heading check before npm publish
  • CHANGELOG.md# Unreleased entries for the two user-facing changes
  • test/* — 22 new/extended tests (see checklist above); the only modified existing tests are the two the issue explicitly targets (errors export list, renewal reschedule)

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI / tooling

Checklist

  • Tests added or updated
  • npm run lint && npm test passes locally (unit: 277 passing, up from 255; coverage 98.33% stmts / 96.23% branch / 100% funcs / 98.33% lines, above the 97/93/100/97 gates)
  • User-facing changes recorded under # Unreleased in CHANGELOG.md
  • All commits have a Signed-off-by: trailer (git commit -s)

@kurok kurok requested review from m2broth and wRLSS as code owners July 2, 2026 11:29
@kurok kurok force-pushed the chore/111-quality-backlog branch from 4179500 to b7ee735 Compare July 2, 2026 11:32
- Wrap non-2xx HTTP responses in a typed VaultHttpError (part of the
  VaultError hierarchy) while preserving the legacy message and the
  statusCode/error field shape, so callers can instanceof-check HTTP
  failures.
- Fail fast with InvalidArgumentsError on missing required auth config:
  role_id for AppRole, role for IAM and Kubernetes; Token auth is now
  null-safe when the config object is missing entirely.
- Cover previously untested paths: the Kubernetes service-account token
  read failure, the prototype-pollution guard in deepMerge (now exported
  for direct testing), Lease#getMetadata, and non-2xx err.error contents
  including the non-JSON-body fallback. The renewal-failure test now
  asserts the refresh timer actually re-arms.
- Document the decision to keep the unmaintained long-timeout dependency.
- Add a release-time check to the publish workflow that CHANGELOG.md
  contains a release-notes heading for the version being published.

Refs #111

Signed-off-by: Yuriy R <22548029+kurok@users.noreply.github.com>
@kurok kurok force-pushed the chore/111-quality-backlog branch from b7ee735 to 6792d05 Compare July 2, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant