Skip to content

Add user Active Sessions, QR remember-me, and new-device alerts - #635

Merged
ddon merged 2 commits into
BeamLabEU:mainfrom
alexdont:main
Jul 14, 2026
Merged

Add user Active Sessions, QR remember-me, and new-device alerts#635
ddon merged 2 commits into
BeamLabEU:mainfrom
alexdont:main

Conversation

@alexdont

Copy link
Copy Markdown
Contributor

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 (the UserSettings component):

  • Lists a user's active sessions: device (browser/OS), location, last-active, IP; marks the current device.
  • Per-session Sign out + Sign out other sessions. Revocation is user-scoped (revoke_user_session/2, revoke_other_user_sessions/2) — a user can't revoke another user's session by guessing a uuid.
  • Degrades gracefully: if known_devices isn'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 location column to phoenix_kit_user_known_devices, populated from the geo lookup LoginAlerts already performs (no extra geo calls per render). Additive, idempotent (add_if_not_exists), with a clean down.

QR login:

  • "Keep me logged in" checkbox + return_to threaded through the handoff (desktop → completion controller), sanitized via Routes.local_path?/1 and handed to the existing log_in_user/3.
  • Phone confirm screen now shows geo-location + a request timestamp.

In-app new-device alert — new "Security" notification type. On a new-device sign-in, LoginAlerts raises an in-app notification via the standalone Notifications.create/1 (the user.new_login_detected activity is self-actor, so the activity→notification hook correctly skips it), linking to Active Sessions. Gated by the existing new_login_alert_enabled setting.

Notes

  • Default behavior: the Active Sessions section shows by default in UserSettings; embedders who don't want it can omit :sessions from the sections assign. QR login and new-login alerts remain off by default.
  • Device name / location in the list populate from known_devices, which are recorded when new_login_alert_enabled is on (privacy-default-off, preserved). Without it, sessions still list with IP + last-active + revoke.
  • Verified: mix compile --warnings-as-errors, mix credo --strict, mix format --check-formatted clean; new tests pass; migrations apply cleanly through V147 (verified end-to-end against a parent app).
  • V147 may need renumbering on merge if it collides with in-flight migrations.

🤖 Generated with Claude Code

Alexander Donand others added 2 commits July 14, 2026 01:18
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
ddon merged commit 1485ab1 into BeamLabEU:mainJul 14, 2026
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>
Sign up for freeto 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.

2 participants

@alexdont@ddon