Skip to content

feat(cache): authenticate remote cache uploads with GitHub Actions OIDC - #798

Merged
wan9chi merged 2 commits into
claude/remote-cache-auth-hook-18e511from
claude/github-oidc-auth-headers-18e511
Oct 5, 2026
Merged

wan9chi merged 2 commits into
claude/remote-cache-auth-hook-18e511from
claude/github-oidc-auth-headers-18e511

Conversation

@wan9chi

@wan9chi wan9chi commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

Motivation

The self-hosted remote cache server in #718, designed in #716, accepts uploads only with a GitHub Actions OIDC token. The token's audience must be the namespace endpoint, and it must come from a push job on the main branch. vp run sends stores without credentials today, so that server rejects every upload with 401.

Changes

  • Planning resolves remote_cache.auth to github-oidc when ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN are set in the envs visible at the vp run level. That happens in jobs with permissions: id-token: write; otherwise the auth stays anonymous.
    • It holds the request URL, the request token, and the audience, which is the endpoint without a trailing slash.
    • The request token is a Secret, which debug output and serialized plans redact.
  • build_auth turns github-oidc into vt_remote_cache::auth::GithubOidc, which adds Authorization: Bearer <token> to stores only. Fetches and downloads stay anonymous.
    • It requests a token when the first store needs one.
    • Later stores reuse the token until two minutes before its exp. Cloudflare receives a store's whole body before the Worker checks the token, so the token has to outlast the upload. A token without exp is a malformed response.
    • Concurrent stores wait for the same request.
    • A failed request is remembered, so later stores fail right away without making more requests. Each task with a failed upload shows the existing "Not uploaded to the remote cache" warning.
    • Neither token appears in debug output or errors.
    • Its state is a single enum: ready with a request and an optional cached token, or failed. A token can't stay cached after a failure.
  • Tasks still receive the two env vars as untracked envs, as in fix(env): pass through GitHub Actions OIDC variables #691, so npm trusted publishing through vp run keeps working.

Stacked on #797, which adds the Auth hook and the resolved auth config.

🤖 Generated with Claude Code

@wan9chi
wan9chi added this pull request to stack #799 October 4, 2026 07:52
@wan9chi
wan9chi force-pushed the claude/github-oidc-auth-headers-18e511 branch from 3f44ec4 to 64b0977 Compare October 4, 2026 07:52
@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

fspy benchmark

linux

dynamic/launch             change  -0.24%  [ -3.88% ..  +4.89%]  overhead  +296.90%
dynamic/access             change  -0.13%  [ -2.32% ..  +1.32%]  overhead   +13.05%
dynamic/access-relative    change  -0.10%  [ -1.47% ..  +1.86%]  overhead   +57.85%
dynamic/access-contended   change  +1.81%  [ -1.31% .. +12.97%]  overhead   +15.10%
static/launch              change  -0.39%  [ -5.23% ..  +5.47%]  overhead  +730.44%
static/access              change  +0.39%  [ -2.42% ..  +3.35%]  overhead  +783.37%
static/access-relative     change  +0.40%  [ -2.40% ..  +3.25%]  overhead +1326.76%
static/access-contended    change  -0.01%  [ -0.96% ..  +1.01%]  overhead +3125.75%

macos

dynamic/launch             change  -0.85%  [ -6.34% ..  +5.29%]  overhead  +237.14%
dynamic/access             change  +0.00%  [ -6.34% ..  +8.82%]  overhead    +3.74%
dynamic/access-relative    change  +1.38%  [-20.43% .. +103.91%]  overhead  +259.56%
dynamic/access-contended   change  +2.24%  [ -4.54% .. +13.02%]  overhead    +3.99%

windows

dynamic/launch             change  -0.31%  [ -3.57% ..  +2.76%]  overhead   +24.00%
dynamic/access             change  +0.00%  [ -1.10% ..  +1.87%]  overhead    +0.94%
dynamic/access-relative    change  +0.18%  [ -1.08% ..  +1.20%]  overhead    +1.47%
dynamic/access-contended   change  +0.00%  [ -1.37% ..  +1.76%]  overhead    +1.25%

@wan9chi
wan9chi force-pushed the claude/github-oidc-auth-headers-18e511 branch 2 times, most recently from e00a71b to 0c99de0 Compare October 4, 2026 12:42
@wan9chi
wan9chi force-pushed the claude/github-oidc-auth-headers-18e511 branch 2 times, most recently from 86869ae to 9c13e94 Compare October 5, 2026 00:51
@wan9chi
wan9chi force-pushed the claude/github-oidc-auth-headers-18e511 branch from 9c13e94 to c724b54 Compare October 5, 2026 01:00
@wan9chi
wan9chi marked this pull request as ready for review October 5, 2026 01:01
wan9chi and others added 2 commits October 5, 2026 10:09
Planning resolves `ResolvedRemoteCacheConfig::auth` to `github-oidc` when
`ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are
set. It holds the request URL, the request token, and the audience,
which is the endpoint without a trailing slash. The request token is a
`Secret`, which debug output and serialized plans redact.

`build_auth` turns it into `vt_remote_cache::auth::GithubOidc`, which adds
a GitHub Actions OIDC token to stores only. It requests a token when the
first store needs it, reuses it until two minutes before it expires,
shares one request between concurrent stores, and remembers a failed
request, so later stores fail without another one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`GithubOidc` keeps its state in one enum, so a token can't stay cached
after a failure, and invalid settings start out failed. A token without
an `exp` claim is now a malformed response, rather than being used once:
the server rejects such tokens anyway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@wan9chi
wan9chi force-pushed the claude/github-oidc-auth-headers-18e511 branch from c724b54 to 238a29c Compare October 5, 2026 02:09
@wan9chi
wan9chi merged commit 8ecec9a into main Oct 5, 2026
19 checks passed
@wan9chi
wan9chi deleted the claude/github-oidc-auth-headers-18e511 branch October 5, 2026 02:14
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