Skip to main content
← Back to list
01Issue
FeatureOpenSwamp CLI
AssigneesNone

Relationships

#578 first-class refresh hook for short-lived vault values (gcloud / aws-sso / kubectl-oidc token UX)

Opened by bixu · 6/6/2026

Summary

Short-lived credential types (gcloud OAuth2 access tokens, AWS SSO tokens, kubectl OIDC tokens, etc.) are awkward to keep fresh inside a swamp vault. Once written via swamp vault put, the stored value is opaque to swamp; if it expires, the only signal is downstream method failure. The standard workaround is a hand-rolled command/shell model (e.g. refresh-gcp-token) that pipes gcloud auth print-access-token | swamp vault put --force ... and is scheduled as the first step of every workflow that needs the credential.

That works, but the per-workflow refresher step is repeated boilerplate that hides intent and is easy to forget when authoring a new workflow.

What good would look like

A first-class refresh hook for vault values that need to be regenerated before each read (or on a TTL). Some shapes worth considering:

  1. Refresh command on the vault entry. When a vault key is registered with a refresh command (e.g. gcloud auth print-access-token), a subsequent vault.get(...) invocation runs the command, writes the result back, and returns the fresh value — all in-process. Authors write the refresh once at vault-put time, then never think about it again.

  2. Per-vault-type refresh adapters. Built-in vault types (@swamp/1password, aws-sm, azure-kv, local_encryption) can declare per-key refresh hooks. User-defined vault types could implement a refresh(key) contract that swamp invokes when a TTL has lapsed or when the consumer marks the value as transient: true.

  3. A workflow-level "ensure fresh" step. A new built-in step type that takes a list of vault keys and refresh commands and runs them only when needed, eliminating the boilerplate command/shell model. (Closest to what people do today, just standardised.)

Why this matters

  • Workflows that touch any short-lived credential gain an extra hand-rolled model and a brittle ordering invariant: forget to put the refresh first and you get an ACCESS_TOKEN_TYPE_UNSUPPORTED / Token expired failure at the IAM step.
  • The refresh boilerplate is per-workflow, not per-credential — repeated everywhere the credential is used.
  • New users routinely store an access token directly and don't understand why it fails an hour later; the failure mode is far from the cause.
  • Once vault:// (or the recommended CEL ${{ vault.get(...) }} form) is in the workflow, the credential's freshness is invisible to the workflow author — there's no way to ask "is this stale?" without going around swamp.
  • swamp Lab #514 — vault://local_encryption token doesn't round-trip correctly for GCP OAuth2 access tokens. The proximate bug is real, but it's downstream of the broader UX gap described here: if vault values had a first-class refresh story, the brittle vault:// round-trip path wouldn't be the workaround surface in the first place.

Suggested scope for a first cut

Start with option 1 (refresh command on the vault entry). It's the smallest viable change, doesn't require workflow-engine work, and would cover the gcloud / aws sso / kubectl oidc / any-cli-that-prints-a-token cases in one shot:

swamp vault put my-vault GCP_TOKEN \
  --refresh-from "gcloud auth print-access-token" \
  --refresh-ttl 50m

Followed by normal use (${{ vault.get(my-vault, GCP_TOKEN) }}) that transparently re-runs the refresh command when the TTL has lapsed and writes the fresh value back to the vault.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

6/6/2026, 1:47:38 PM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.