Skip to content

deps: migrate jwt/xsync/errors libraries + add jwtutil helper#1606

Merged
paulwe merged 13 commits into
mainfrom
deps/upgrade-xsync-and-go-jose-v4
Jun 5, 2026
Merged

deps: migrate jwt/xsync/errors libraries + add jwtutil helper#1606
paulwe merged 13 commits into
mainfrom
deps/upgrade-xsync-and-go-jose-v4

Conversation

@paulwe
Copy link
Copy Markdown
Contributor

@paulwe paulwe commented Jun 4, 2026

Summary

Source-level migration off three unmaintained / breaking-changed deps, plus an internal helper to insulate downstream consumers from JWT library churn.

  • go-jose/v3 -> golang-jwt/jwt/v5 (auth/accesstoken.go, auth/verifier.go, tests). Took a brief detour through go-jose/v4 (4ec1794) before switching to golang-jwt (878cf9b) because go-jose/v4 enforces an HS256 >=32-byte secret minimum that breaks the OSS livekit-server --dev default. golang-jwt/v5 matches v3's permissive behavior and is ~18x more popular.
  • xsync/v3 -> v4MapOf is now an alias for Map; LoadOrCompute callback signature changed to func() (V, bool) (the new bool is "cancel").
  • pkg/errors -> stdlib errors / fmt.Errorf %w (b6c88bd). Also dropped go.uber.org/atomic in the same commit, then reverted (ab1b54f) when it produced ABI friction with downstream cloud-protocol struct fields.
  • utils/jwtutil (29568b8) — new package wrapping *jwt.Parser + an HMACKeySet for kid-based key rotation, so cloud-protocol/s2sa and other consumers don't each re-implement the verifier.
  • webhook test fixture (658576c) — bumped the HS256 secret in tests to satisfy go-jose v4's length minimum during the intermediate commit; left in place after the golang-jwt switch since longer secrets are still better.
  • go get -u sweep + counterfeiter v6.12.2 (a7a83da).

Downstream impact

  • auth.APIKeyTokenVerifier internals changed (no longer holds a *jose.JSONWebToken); public API is unchanged.
  • utils/jwtutil is the new recommended way to verify JWTs against a rotated key set; cloud-protocol's worker token provider already consumes it.

Test plan

  • go build ./...
  • go test ./... (modulo pre-existing Docker/Postgres/AWS-creds-gated tests)

xsync v4: MapOf is an alias for Map; the LoadOrCompute callback
signature changed to return (V, bool), so existing call sites pass
false as the cancel flag.

go-jose v4: jwt.ParseSigned now requires an explicit signature-
algorithm allowlist (HS256, matching what we sign with), and
Builder.CompactSerialize was renamed to Serialize. v4 also enforces
RFC 7518's HMAC key-size minimum (HS256 ≥ 32 bytes); secrets issued
via utils.RandomSecret already satisfy this, but any deployment using
a custom shorter secret will now hit ErrInvalidKeySize.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 4, 2026

⚠️ No Changeset found

Latest commit: 5e03336

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

go-jose v4 enforces RFC 7518's HMAC key-size minimum (HS256 requires
keys ≥ 32 bytes), which would break OSS deployments using short
secrets — including the livekit-server --dev default ("devkey":"secret").
golang-jwt/jwt/v5 does not enforce a minimum, preserving the previous
behavior.

The new combined tokenClaims struct embeds jwt.RegisteredClaims with
ClaimGrants so the on-wire payload is unchanged. A token leeway of one
minute is set to match go-jose's previous DefaultLeeway. Verify now
re-parses the raw token string (golang-jwt does not separate parsing
from signature verification), and its first return type changes from
*jose.Claims to *jwt.RegisteredClaims; all in-tree callers ignore that
return.

Reverts the test secret bumps from the previous commit since the
length requirement no longer applies.
@paulwe paulwe changed the title deps: upgrade xsync v3→v4 and go-jose v3→v4 deps: upgrade xsync v3→v4; replace go-jose with golang-jwt/jwt/v5 Jun 4, 2026
pkg/errors was unmaintained since 2021 and stdlib errors + fmt.Errorf
%w covers our (wrap-only) usage. Removed from redis/redis.go and
observability/egressobs/egress.go.

go.uber.org/atomic moves to sync/atomic, which gained generic typed
values in Go 1.19+. Most call sites are straightforward import swaps
plus s/.Inc()/.Add(1)/. atomic.NewUint64(0) becomes var ... atomic.Uint64.

Three stdlib gaps required local wrappers:
- configutil.AtomicFloat32/Float64 (Uint32/Uint64 + math.Floatbits)
- configutil.AtomicDuration (Int64)
- configutil.AtomicString, AtomicTime (atomic.Pointer)
- utils/hwstats/cpu.go uses a private atomicFloat64 with the same trick

go.uber.org/atomic remains an indirect dep via backend-common; protocol
no longer pulls it directly.

This is a breaking change for callers of configutil.NewAtomic* helpers
that named the returned type explicitly: uber.org/atomic.Bool returns
become sync/atomic.Bool, and Float32/Float64/String/Duration/Time
returns become *configutil.Atomic<T> wrappers.
Copy link
Copy Markdown
Contributor

@biglittlebigben biglittlebigben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment thread logger/pionlogger/zaplogadapter.go Outdated
The stdlib sync/atomic migration was reverted because:
- sync/atomic lacks Float32/Float64/String/Duration/Time types, requiring
  shim types around bit-packing or atomic.Pointer that complicate the
  configutil public API and don't carry their weight at this scale.
- configutil.NewAtomic* return-type changes cascade as breaking changes
  across all downstream consumers.

pkg/errors → stdlib stays. jwt and xsync upgrades stay.
@paulwe paulwe changed the title deps: upgrade xsync v3→v4; replace go-jose with golang-jwt/jwt/v5 deps: upgrade protocol — golang-jwt v5, xsync v4, pkg/errors → stdlib Jun 4, 2026
paulwe added 3 commits June 4, 2026 14:35
Restores the convenience that go-jose's JSONWebKeySet provided when picking
the right key from a set during verification, which golang-jwt/jwt/v5 leaves
to the caller. The new utils/jwtutil package wraps the manual kid lookup +
WithValidMethods enforcement that has to repeat at every signer/verifier
site otherwise.

Also fixes a stale ST1005 (capitalized error string) in redis/redis.go
that surfaced after the pkg/errors → stdlib swap.
Direct deps bumped:
  hashicorp/go-retryablehttp 0.7.7 -> 0.7.8
  mackerelio/go-osstat 0.2.5 -> 0.2.7
  maxbrunsfeld/counterfeiter/v6 v6.11.1 -> v6.12.2
  nyaruka/phonenumbers v1.6.5 -> v1.8.0
  prometheus/client_golang 1.22.0 -> 1.23.2
  prometheus/procfs 0.16.1 -> 0.20.1
  otel/exporters/otlp/otlptrace/otlptracehttp + sdk 1.43.0 -> 1.44.0

No newer major versions actionable. phonenumbers v2.0.0-rc1 exists but
is release-candidate only. twitchtv/twirp v8.1.3+incompatible stays
(upstream has no module-aware path).
@paulwe paulwe changed the title deps: upgrade protocol — golang-jwt v5, xsync v4, pkg/errors → stdlib deps: migrate jwt/xsync/errors libraries + add jwtutil helper Jun 5, 2026
paulwe and others added 5 commits June 5, 2026 00:01
Verifies that compact JWTs produced by jwtutil's HMACKeySet are still
readable by go-jose v4 consumers, and vice versa, after the switch from
go-jose/v4 to golang-jwt/jwt/v5. go-jose/v4 is added as a test-only
dependency; the 32-byte key satisfies its HS256 minimum.
pion/sctp v1.10.0 (and the paired pion/webrtc/v4 v4.2.14 that needs
its new API) causes a regression in livekit-server's
TestDataPublishSlowSubscriber. Pinning here so downstream consumers
pick the safe versions via MVS.
@paulwe paulwe merged commit c0615a2 into main Jun 5, 2026
5 checks passed
@paulwe paulwe deleted the deps/upgrade-xsync-and-go-jose-v4 branch June 5, 2026 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants