Skip to content

revert(jwt): restore the 30-day token lifetime - #434

Merged
Ryanmello07 merged 1 commit into
urnetwork:mainfrom
Ryanmello07:revert/jwt-30-day-lifetime
Aug 12, 2026
Merged

revert(jwt): restore the 30-day token lifetime#434
Ryanmello07 merged 1 commit into
urnetwork:mainfrom
Ryanmello07:revert/jwt-30-day-lifetime

Conversation

@Ryanmello07

Copy link
Copy Markdown
Contributor

Reverts expiryDuration from 24h back to 30 days, per team decision. Already deployed and running on beta.

Why

The one-day value bounded stale authorization for a client that stays online indefinitely, which is a real thing to want. It rested on a premise stated in its own comment — "SDK APIs refresh at half-life and retry before this deadline, so conforming clients rotate without a protocol change."

That premise holds for the sdk only since the half-life refresh landed on 2026-08-06 (urnetwork/sdk 8ed3101). It does not hold for anything else holding a token: an app build older than that, or any client issued a token it never refreshes.

What that looked like in production

A non-refreshing client does not fail loudly at the deadline. It stays connected, keeps accepting connections, and carries nothing — healthy from every angle except an egress probe.

Measured on beta, probe success by client age at probe time:

provider age when probed attempts success
under 6h 960 95%
6–12h 1,610 95%
12–20h 224 58%
20–24h 266 14%
24–30h 104 0%
over 30h 166 0%

A fleet-wide blackhole on a 24h clock — 270 consecutive failures past the deadline, and invisible to everything that was not probing egress. It was diagnosed only because a probe asked providers to actually carry traffic.

What this does and does not fix

It does not repair anything on its own. A token already issued keeps its original expiry, so a client that has gone dark stays dark until it re-authenticates. The longer lifetime applies only to tokens minted from here.

Nor does it fix the non-refreshing client. It makes the deadline rare enough to be noticed rather than routine.

The durable protections are elsewhere and stay in place:

Shortening this again is reasonable once a client that ignores the deadline is the exception rather than the rule — the comment on the constant says so, so the next person to consider it has the context that was missing this time.

The test

TestByJwtLifetimeIsOneDay is updated rather than deleted, and now records why it asserts a value at all: clients schedule their own rotation against this number, and the two have already fallen out of step once.

Verification

go build ./jwt/... ./model/... ./api/..., go vet ./jwt/, gofmt -l clean, and go test ./jwt/ passes against a live postgres. Running on beta since deploy — a token minted through /auth/login comes back with a 30.0 day lifetime.

Reverts the expiryDuration change from 24h back to 30 days, by team decision.

The one-day value bounded stale authorization for a client that stays online
indefinitely, which is a real thing to want. It rested on the premise that
conforming clients rotate at half-life -- true of the sdk only since the
half-life refresh landed on 2026-08-06, and not true of anything else holding a
token: an app build older than that, or any client issued a token it never
refreshes.

Those clients do not fail loudly at the deadline. They stay connected, keep
accepting connections, and carry nothing -- healthy from every angle except an
egress probe. Measured on beta by provider age at probe time:

  <6h      95% probe success
  6-12h    95%
  12-20h   58%
  20-24h   14%
  24-30h    0%   (104 attempts)
  >30h      0%   (166 attempts)

A fleet-wide blackhole on a 24h clock, invisible to everything that was not
probing egress.

This does not repair anything on its own. A token already issued keeps its
original expiry, so a client that has gone dark stays dark until it
re-authenticates; the longer lifetime only applies to tokens minted from here.
Nor does it fix the non-refreshing client -- it makes the deadline rare enough
to be noticed rather than routine.

The durable protections are elsewhere and stay in place: the sdk's half-life
rotation, and the server refusing to advertise a provider whose egress health
has aged out (ProviderEgressHealthMaxAge). Shortening this again should wait
until a client that ignores the deadline is the exception rather than the rule.

The lifetime test is updated rather than deleted, and says why it asserts a
value at all: clients schedule rotation against this number, and the two have
already fallen out of step once.

(cherry picked from commit dce6442)
@Ryanmello07
Ryanmello07 merged commit 6af7e02 into urnetwork:main Aug 12, 2026
1 check passed
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