Skip to content

feat(vault): cache KV version preflight and secret map reads#1

Closed
digiserg wants to merge 2 commits into
masterfrom
feat/vault-provider-cache
Closed

feat(vault): cache KV version preflight and secret map reads#1
digiserg wants to merge 2 commits into
masterfrom
feat/vault-provider-cache

Conversation

@digiserg

Copy link
Copy Markdown
Collaborator

Summary

  • Cache isKVv2 preflight results per mount path — eliminates repeated GET /v1/sys/internal/ui/mounts/<path> calls for the same mount
  • Cache GetStringMap results per secret path — eliminates repeated reads when multiple keys are pulled from the same path
  • Reorder provider struct fields for optimal memory alignment (240→232 bytes)

Motivation

Each secret reference in a vals-processed YAML file previously cost two Vault API calls:

  1. GET /v1/sys/internal/ui/mounts/<path> — KV version preflight
  2. ReadWithData — secret read

For N secrets this meant 2N token uses, which breaks Vault tokens created with a low -use-limit (e.g. -use-limit=1 fails immediately).

With both caches, token use-limit needed = unique_mounts + unique_secret_paths (typically P+1 for a single mount with P distinct paths).

Test plan

  • go build ./... passes
  • go vet ./... clean
  • golangci-lint run clean (0 issues)
  • Integration tests skipped — require a live Vault instance

Assisted-by: Claude Code

https://claude.ai/code/session_01RDWpvGwQQzRfWUYhohzhNk

digiserg added 2 commits June 26, 2026 15:39
Without caching, each secret ref in creds.yaml costs two Vault API
calls: one preflight to /v1/sys/internal/ui/mounts/<path> to detect
KV v1/v2, and one ReadWithData for the secret itself. This exhausts
low use-limit tokens (e.g. -use-limit=1) immediately.

With both caches:
- kvVersionCache: one preflight per unique mount path per run
- secretMapCache: one read per unique secret path per run

For N secrets across M unique mounts under P unique paths, token
use-limit needed drops from 2N to M+P (typically P+1 for single mount).

Claude-Session: https://claude.ai/code/session_01RDWpvGwQQzRfWUYhohzhNk
Signed-off-by: Sergio Rua <[email protected]>
Moving map fields before string fields reduces struct size from 240
to 232 bytes (8-byte saving) by avoiding padding between pointer-sized
and string-sized fields.

Claude-Session: https://claude.ai/code/session_01RDWpvGwQQzRfWUYhohzhNk
Signed-off-by: Sergio Rua <[email protected]>
@digiserg digiserg closed this Jun 30, 2026
digiserg added a commit that referenced this pull request Jun 30, 2026
Address PR review (helmfile#1213):

- Replace the never-evicting secretMapCache with singleflight dedup of
  concurrent reads, so a burst of parallel callers (vals-operator) costs
  one Vault read/token-use instead of N, without ever serving stale
  secrets (#1, helmfile#2, helmfile#3).
- Return a per-caller copy of the map since singleflight shares one
  result by reference (helmfile#2).
- Key the KV-version cache by mount path so sibling secrets under the
  same mount share a single preflight (helmfile#4).
- Serialize lazy client creation/auth in ensureClient to remove the
  first-use race (helmfile#6).
- Add concurrency tests asserting preflight/read call counts and map
  isolation against a stubbed Vault server (helmfile#5).
- Drop the hand-wavy fieldalignment nolint; order fields cleanly (helmfile#7).

Signed-off-by: Sergio Rua <[email protected]>
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