Skip to content

fix(core): resolve credential aliases after revision eviction - #4390

Merged
mrunalp merged 1 commit into
NVIDIA:mainfrom
stevenlee-oai:fix/4382-credential-alias-identity/stevenlee-oai
Oct 9, 2026
Merged

mrunalp merged 1 commit into
NVIDIA:mainfrom
stevenlee-oai:fix/4382-credential-alias-identity/stevenlee-oai

Conversation

@stevenlee-oai

Copy link
Copy Markdown
Contributor

Summary

A revision-based credential alias works while its issued revision remains cached. After credential rotation evicts that revision, the normal placeholder can fall back to the current credential for the same provider identity, but the equivalent alias fails to take that fallback and returns Unavailable.

Convert the alias into the normal placeholder before lookup so both forms use the existing revision-fallback logic. Also preserve EndpointMismatch reporting when an alias is used at a disallowed endpoint.

Related Issue

Closes #4382.

Replaces #4383, which the contributor gate closed before the author was vouched.

Changes

Both forms work initially

Suppose OpenShell issues credential revision 50. These two values identify the same credential; H and P stand for encoded JWT header and payload segments:

Normal placeholder:
  openshell:resolve:env:v50_API_KEY

JWT-shaped alias:
  H.P.OPENSHELL-RESOLVE-ENV-v50_API_KEY

While revision 50 remains cached and usable, both resolve successfully. JWT is only an example of the existing alias convention; the bug also affects non-JWT aliases.

The failure starts when the old revision leaves the cache

After enough credential updates, revision 50 leaves the eight-generation retention window. OpenShell already allows an old issued revision to use the current credential if it still belongs to the current provider identity.

Before this fix:

Normal placeholder:
  recognize revision 50
  -> validate its provider identity
  -> resolve the current API_KEY credential
  -> succeeds

Alias:
  extract "v50_API_KEY"
  -> treat that entire suffix as a lookup key
  -> look for the old cached entry, which is now gone
  -> fails with Unavailable

The refreshed credential is available. The alias path simply never reaches the existing fallback for it. These are opaque credential-state revisions, not software versions, and they need not increase numerically.

Normalize first, then use the existing resolver

The fix moves alias conversion to the start of resolve_placeholder():

H.P.OPENSHELL-RESOLVE-ENV-v50_API_KEY
  -> openshell:resolve:env:v50_API_KEY
  -> recognize revision 50
  -> validate its provider identity
  -> resolve the current API_KEY credential

Both forms now follow the same exact lookup and authorized revision fallback. Remove the redundant late alias path. Old aliases remain rejected when their provider identity is removed or replaced; expiry and endpoint restrictions still apply.

The second change extracts the actual environment key from revision and stable-handle alias suffixes in placeholder_env_key(). A wrong-endpoint alias now reports EndpointMismatch instead of Unavailable; both versions reject that request.

This is an alias-resolution lifecycle fix, not a JWT parsing or refresh-exchange fix. Stable-handle aliases already work across rotation on main. Ordinary bearer tokens without reserved markers remain unchanged. Documentation describes JWT-shaped aliases as one use of the existing convention.

Testing

  • Reproduced both regression failures with the unchanged main resolver at 61d42102c.
  • cargo test --locked -p openshell-core --lib: 535 passed. An initial run hit an unrelated e2fsprogs temporary-script Text file busy error; the complete rerun passed.
  • cargo clippy --locked -p openshell-core --all-targets -- -D warnings and changed-file Rust formatting checks passed.
  • Fern 5.112.0 check: zero errors; docs navigation check passed. Fern reports existing gateway-configuration MDX and theme-contrast warnings, and skips authenticated redirect checking without a token.
  • Independent correctness and design/test reviews found no remaining actionable issues.
  • Deployed sandbox E2E was not rerun; the runtime evidence here is the real shared resolver and serialized HTTP rewrite exercised by the crate tests.

Checklist

  • Follows Conventional Commits.
  • Commit is signed off for DCO.
  • Provider documentation updated.

Signed-off-by: Steven Lee <stevenlee@openai.com>
@copy-pr-bot

copy-pr-bot Bot commented Oct 9, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@mrunalp

mrunalp commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

/ok to test 5c9b79e

@mrunalp mrunalp added the test:e2e Requires end-to-end coverage label Oct 9, 2026
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Label test:e2e applied for 5c9b79e. Open the existing run and click Re-run all jobs to execute with the label set. The run will execute the standard E2E suite after building the required gateway, sandbox, and supervisor images once. The matching required CI gate status on this PR will flip green automatically once the run finishes.

@mrunalp
mrunalp added this pull request to the merge queue Oct 9, 2026
Merged via the queue into NVIDIA:main with commit 0ccc6b9 Oct 9, 2026
120 of 121 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: preserve credential alias identity across rotation

2 participants