Uh oh!
There was an error while loading. Please reload this page.
Add user Active Sessions, QR remember-me, and new-device alerts - #635
Merged
Conversation
Extends the QR device-handoff login and adds a self-service session management surface, built on the existing session-fingerprinting and new-login (V143 known-devices) infrastructure. - Active Sessions section in /dashboard/settings: lists a user's active sessions with device (browser/OS), location, last-active and IP, marks the current device, and offers per-session "Sign out" + "Sign out other sessions". Revocation is user-scoped so one user can never revoke another's session. Degrades gracefully (IP-only) if the known-devices table isn't migrated yet, so it never crashes the settings page. - V147 migration: persist geo-location on known devices (nullable column), populated from the lookup LoginAlerts already performs — no extra geo calls per page render. - QR login: "Keep me logged in" checkbox and return_to threaded through the handoff to the completion controller (sanitized via Routes.local_path?); the phone confirm screen now shows geo-location + request timestamp. - In-app new-device alert: a new "Security" notification type; on a new-device sign-in LoginAlerts also raises an in-app notification (via the standalone Notifications.create/1, since the activity is self-actor) linking to Active Sessions. Gated by the existing new_login_alert setting. - Tests: QR mint/approve/consume single-use, session enrichment, and the user-scoped revoke guards. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MsjUy1HnuJnCSrqdbnANYL
IpAddress.extract_from_socket/1 returns the literal "unknown" when peer data is unavailable (proxies, some transports). device_meta/1 passed that straight through, so the phone confirm screen rendered "unknown" as the IP and fed the placeholder into the geo lookup. Normalize a missing/"unknown"/blank IP to absent so the confirm screen omits the IP row entirely (and skips the location lookup), and add a rescue to location_for/1 so a geo-backend hiccup can't crash the QR mint. Approval was — and stays — allowed when the IP is absent; it's informational, not a gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MsjUy1HnuJnCSrqdbnANYL
ddon pushed a commit
that referenced
this pull request
Jul 14, 2026
Post-merge review of PR #635 (Active Sessions, QR remember-me, new-device alerts): bounded the QR page's geolocation lookup to 1.5s via an unlinked supervised Task so a slow/unreachable geo API no longer stalls the QR code behind a ~10s synchronous call, and corrected Russian/Estonian translations for the new session-management strings — including a fuzzy-matched "Sign out" that had been translated as "Log in" in both locales. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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 freeto 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.
What
Builds on the QR device-handoff login (#630) and the V143 known-devices / new-login infrastructure to add a self-service Active Sessions surface plus QR/login-security polish. Everything is additive or behind existing default-off settings.
Changes
Active Sessions — new section in
/dashboard/settings(theUserSettingscomponent):revoke_user_session/2,revoke_other_user_sessions/2) — a user can't revoke another user's session by guessing a uuid.known_devicesisn't migrated yet, enrichment is skipped (IP-only) instead of crashing the settings page — safe for the deploy→migrate window.V147 migration — adds a nullable
locationcolumn tophoenix_kit_user_known_devices, populated from the geo lookupLoginAlertsalready performs (no extra geo calls per render). Additive, idempotent (add_if_not_exists), with a cleandown.QR login:
return_tothreaded through the handoff (desktop → completion controller), sanitized viaRoutes.local_path?/1and handed to the existinglog_in_user/3.In-app new-device alert — new "Security" notification type. On a new-device sign-in,
LoginAlertsraises an in-app notification via the standaloneNotifications.create/1(theuser.new_login_detectedactivity is self-actor, so the activity→notification hook correctly skips it), linking to Active Sessions. Gated by the existingnew_login_alert_enabledsetting.Notes
UserSettings; embedders who don't want it can omit:sessionsfrom thesectionsassign. QR login and new-login alerts remain off by default.known_devices, which are recorded whennew_login_alert_enabledis on (privacy-default-off, preserved). Without it, sessions still list with IP + last-active + revoke.mix compile --warnings-as-errors,mix credo --strict,mix format --check-formattedclean; new tests pass; migrations apply cleanly through V147 (verified end-to-end against a parent app).🤖 Generated with Claude Code