Repository navigation
feat: give sessions a key change ends their own reason - #80
Open
leviFrosty wants to merge 1 commit into
Open
leviFrosty wants to merge 1 commit into
leviFrosty wants to merge 1 commit into
Conversation
leviFrosty
force-pushed
the
key-changed-reason
branch
from
October 31, 2026 17:18
c5f13df to
391fe5d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A key change now ends the account's other live sessions with their own reason,
key_changed. Before, it usedrevoked, the same as signing a device out.Until now a browser couldn't tell two cases apart:
Both refreshes answered
revoked.ended_reason = 'key_changed'for them. Sessions signed out or revoked before the change keep their reason.reason: "key_changed"for those sessions, withchangedAt(when the key changed, askey_retiredgives it).REFRESH_REFUSALSandSESSION_END_REASONSgain it.ended_reasonis plain text, so there's no migration.session.revokedwith the changing session as actor).key_changedwithchangedAt, and their rows say so. A session expired before the change refreshes asexpired. Sessions signed out or revoked before the change keep their row and refresh asrevoked.key_changed. A session revoked before the change getsrevoked.expired.key_changedside by side. On a call, the access token is older than the session's own key change, so refresh. On a refresh, the session is over. The rekey description says other live sessions end withended_reason: key_changed.App side: witness-work #1239 keeps a browser's data on
key_changedalone (no probe), and everyrevokedwipes. Phones treat any refused refresh the same way, by reopening, so the new reason needs nothing there.Checks: unit tests (2,000 passed), e2e on a local worker (
dev.mjs up --persist-to /tmp/ww-verify-w5kcr2, port 8792; 134 passed, 23 skipped), both with--maxWorkers=4, andpnpm typecheck.Deploy order: deploy this before witness-work #1239's web build. Otherwise a browser signed out by a key change reads
revokedand wipes. That's fail-safe, but it loses that browser's edits made offline.