Skip to content

Release v0.58.0 - #6957

Merged
rdimitrov merged 1 commit into
mainfrom
release/v0.58.0
Oct 27, 2026
Merged

rdimitrov merged 1 commit into
mainfrom
release/v0.58.0

Conversation

@toolhive-release-app

Copy link
Copy Markdown
Contributor

Release v0.58.0

Version Bump

minor release

Files Updated

  • VERSION
  • deploy/charts/operator-crds/Chart.yaml (path: version)
  • deploy/charts/operator-crds/Chart.yaml (path: appVersion)
  • deploy/charts/operator/Chart.yaml (path: version)
  • deploy/charts/operator/Chart.yaml (path: appVersion)
  • deploy/charts/operator/values.yaml (path: operator.image)
  • deploy/charts/operator/values.yaml (path: operator.toolhiveRunnerImage)
  • deploy/charts/operator/values.yaml (path: operator.vmcpImage)
  • Helm chart docs (via helm-docs)

Next Steps

  1. Review this PR
  2. Merge to main
  3. Release automation will handle the rest

Checklist

  • Version bump is correct
  • All CI checks pass

Release-Triggered-By: rdimitrov
@github-actions github-actions Bot added the size/XS Extra small PR: < 100 lines changed label Oct 27, 2026
@codecov

codecov Bot commented Oct 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.15%. Comparing base (c80a999) to head (cef317a).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6957      +/-   ##
==========================================
- Coverage   80.20%   80.15%   -0.06%     
==========================================
  Files         845      845              
  Lines       85649    85649              
==========================================
- Hits        68696    68652      -44     
- Misses      16948    16992      +44     
  Partials        5        5              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rdimitrov
rdimitrov merged commit c0b163c into main Oct 27, 2026
43 checks passed
@rdimitrov
rdimitrov deleted the release/v0.58.0 branch October 27, 2026 12:03
@github-actions

Copy link
Copy Markdown
Contributor

📝 Generated release notes for v0.58.0

Auto-generated by the release-notes skill. Review and, if good, apply with:

gh release edit v0.58.0 --notes-file <paste-below>.md
Click to expand release notes

🚀 Toolhive v0.58.0 is live!

This release hardens the embedded authorization server. Delegate clients removed from config are now refused, refresh grants for sessions whose upstream credential is dead are refused, upstream identity is no longer stored when nothing reads it, and Go embedders can opt in to RFC 9068 at+jwt access tokens.

⚠️ Breaking Changes

  • Delegate clients removed from config are now refused: a delegate client that is no longer in the auth server config now gets invalid_client. This covers clients removed in earlier releases whose rows are still in Redis. Before upgrading, check Redis for leftover client rows. During a rolling update, upgrade every replica before you add new delegates. (migration guide)
Migration guide: Delegate clients removed from config are now refused

Who is affected: deployments of the embedded authorization server that use Redis storage and configure delegate clients. Go embedders that call ReconcileConfiguredClient or RegisterClient are also affected.

Until now, removing a delegate client from config did not revoke it. Its row stayed in Redis, and the client could still authenticate with its stored secret or keys. Each row written from config is now stamped as configured. Each replica serves a configured row only while its own config still declares that client ID. Rows from releases before the stamp existed are recognized by the legacy delegate shape. Admission never deletes or rewrites a row.

Observable changes

  • Removed delegates: they get invalid_client, starting with the first start of v0.58.0. Access tokens already issued to them stay valid until they expire.
  • Rolling updates: a replica that runs v0.58.0 with the old config refuses a newly added delegate until that replica restarts with the new config.
  • Rollback: a binary from before this release serves a removed delegate's row again.
  • Pending requests whose client no longer resolves:
    • Consent and the upstream callback now answer with a plain-text HTTP 400 containing invalid_client, and send nothing upstream. Before, consent answered 500 and the callback exchanged the upstream code before failing.
    • Device verification answers 400 and never authorizes the request.
  • Go embedders:
    • ReconcileConfiguredClient now accepts only *fosite.DefaultClient and *fosite.DefaultOpenIDConnectClient. Rows it writes are hidden unless the client ID is in DelegateClients.
    • RegisterClient refuses a client that carries the configured stamp.
    • A confidential *fosite.DefaultClient stored with RegisterClient whose only grant type is token-exchange matches the legacy delegate shape. It is hidden unless it is declared as a delegate. On Redis this also applies to an OIDC client of that shape with no token endpoint auth method.

Before

# Delegate "ci-broker" removed from config, server restarted on Redis
POST /oauth/token  (client_id=ci-broker, valid stored credentials)
→ 200 OK, new tokens issued

After

# Same request on v0.58.0
POST /oauth/token  (client_id=ci-broker, valid stored credentials)
→ 401 {"error":"invalid_client"}

Migration steps

  1. Before upgrading, list leftover client rows with SCAN {prefix}client:*. If a workload still uses a delegate that is no longer in config, add that delegate back to config.
  2. Roll the new binary out to every replica first. Add new delegates to config only after the rollout finishes.
  3. If a revocation must still hold after a rollback, delete the removed delegate's row with DEL {prefix}client:{client_id}.
  4. Go embedders that store their own clients should use RegisterClient instead of ReconcileConfiguredClient. A token-exchange-only confidential client registered this way must be declared in DelegateClients, or given a different grant-type shape.

PR: #6945 — Fixes #6477

🔄 Deprecations

  • Using the token endpoint URL, or an aud array with several values, as the audience of a private_key_jwt client assertion is deprecated in favour of the authorization server issuer as the only aud value, as draft-ietf-oauth-rfc7523bis §4 requires. The issuer is now accepted alongside the old forms, and a future release (version not yet set) will require the issuer as the sole value. (#6945, from #6946)

🆕 New Features

  • Go embedders can now have the embedded authorization server sign access tokens with the RFC 9068 typ: at+jwt JOSE header, using runner.WithAccessTokenType("at+jwt") or authserver.Config.AccessTokenType. This applies to every grant, and the default stays typ: JWT. (#6942)
  • private_key_jwt client assertions now accept the authorization server issuer as the aud, either as a string or inside an array, so clients that follow draft-ietf-oauth-rfc7523bis are no longer refused. (#6945, from #6946)

🐛 Bug Fixes

  • A refresh grant for a session whose upstream credential is dead now returns 400 invalid_grant instead of new tokens, which sends the client to a full sign-in. Before, the client kept getting new tokens for the same dead session and looped on 401.
    • This guard is on by default whenever an upstream is configured, and refresh tokens now stay usable only as long as the upstream credential does.
    • When the stored upstream token has expired, the server first tries to refresh it upstream, which can delay the refresh grant (the check gives up and lets the grant through after 10 seconds).
    • Go embedders can turn the guard off with Config.DisableUpstreamRefreshGuard. There is no CLI or CRD switch yet (#6931).
    • (#6930)
  • The embedded authorization server no longer stores the user's verified upstream identity at login while SubjectIdentifierAudiences is empty, which is the default. Nothing reads that data in that case, so this reduces the stable user identifiers kept at rest. If a Go embedder later enables disclosure, sub_id and upstream_subject appear only for logins made after the change. (#6956)
  • Fixed the pkg/authserver test build on main, which broke when two PRs that each passed CI on their own were merged together. (#6950)

🧹 Misc

  • Gave the operator's embedded-auth ConfigMap helpers (field index, watch mappers, rollout checksum) generic names before they are reused for JWKS ConfigMap references. The rollout annotation value and the field-index name are unchanged, so pods do not restart on upgrade. (#6951)

📦 Dependencies

Module Version
k8s.io/utils ca04ba5 (digest)
Full commit log

What's Changed

Full Changelog: v0.57.0...v0.58.0

🔗 Full changelog: v0.57.0...v0.58.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release size/XS Extra small PR: < 100 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant