Skip to content

Device management: list, key status, session revocation, naming, suspicious-login warnings, recovery escalation#772

Open
Timrossid wants to merge 21 commits into
Stellar-Mail:mainfrom
Timrossid:feature/device-management
Open

Device management: list, key status, session revocation, naming, suspicious-login warnings, recovery escalation#772
Timrossid wants to merge 21 commits into
Stellar-Mail:mainfrom
Timrossid:feature/device-management

Conversation

@Timrossid

@Timrossid Timrossid commented Jun 17, 2026

Copy link
Copy Markdown

Why this matters

Users need visibility and control over which devices can decrypt mail or authorize protocol actions.

What's implemented

Backend API (11 endpoints)

  • GET /devices — List registered devices with session info
  • POST /devices/register — Register a new device with fingerprint dedup
  • GET /devices/recovery — Account recovery status
  • GET /devices/:id — Read specific device
  • PUT /devices/:id/name — Rename a device
  • POST /devices/:id/trust — Toggle device trust status
  • POST /devices/:id/revoke — Revoke device and all sessions
  • POST /devices/:id/compromised — Flag device as compromised
  • POST /devices/rotate-keys — Rotate encryption keys for devices
  • GET/POST /devices/recovery-methods — List/create recovery methods
  • DELETE /devices/recovery-methods/:id — Remove recovery method
  • POST /sessions/:id/revoke — Revoke specific session

Domain Model

  • Device schema with key status lifecycle: active, compromised, revoked, rotated
  • Session schema with revocation tracking
  • RecoveryMethod schema (trusted_contact, hardware_key, paper_key, encrypted_backup)

Device Service

  • Device registration with fingerprint dedup (rejects revoked/compromised re-registration)
  • Device naming, trust toggling, revocation, compromise flagging
  • Key rotation (marks old keys as rotated, creates new device entries)
  • Suspicious login detection (unrecognized device, compromised device)
  • Recovery methods CRUD with ownership validation

Audit Log (7 new event kinds)

All security-category, no message body content:

  • device.registered, device.renamed, device.revoked, device.trust_toggled
  • device.key_rotated, device.recovery_activated, device.suspicious_login

Frontend UI (Security tab in Settings)

  • Current device identification banner with "This device" badge
  • Security alert banner (pulsing icon) for compromised devices
  • Warning banner for revoked devices
  • Device list with key status badges (Active/Compromised/Revoked/Rotated)
  • Inline device renaming with Enter/Escape support
  • Trust toggling per device with visual feedback
  • Revoke device with detailed consequence explanation
  • One-click compromised device flagging with session + key invalidation
  • Key rotation with confirmation dialog and loading spinner
  • Recovery methods management: add with type selector form, list with icons, remove with confirmation
  • Device registration prompt when no devices exist
  • Encryption key display with copy and rotation
  • Error banner with dismiss, toast notifications (sonner) for all actions
  • Revocation consequences expandable info panel

Tests

19 comprehensive unit tests covering all device service functions.

OpenAPI Documentation

All 11 device/session endpoints documented with schemas for Device and RecoveryMethod.

Acceptance Criteria

  • Current device is clearly identified
  • Revocation consequences are explained
  • Compromised device can be disabled quickly
  • Audit history excludes sensitive content

Success Signal

A user revokes a lost device and confirms future access denial in under two minutes.

Closes #73

…CI checks

- Add useFocusTrap hook for focus trapping and restoration across all dialogs
- Add jsx-a11y ESLint plugin and axe-core Playwright for CI checks
- Fix primary flows keyboard completeness (arrow nav, escape handlers)
- Fix focus restoration after overlays close (ShortcutOverlay, CommandPalette,
  ProofInspectorModal, SenderConversionDialog, SnoozeDialog, SettingsModal, Compose)
- Add live region announcements (aria-live) for proof inspector and app root
- Fix ARIA roles: dialog attributes on SettingsModal, Compose, provenance modal
- Fix EmailList invalid listbox role (changed to list)
- Add aria-labels to icon-only buttons in EmailView, Sidebar collapsed state
- Add aria-current to sidebar navigation, aria-label to nav landmarks
- Add Escape key handlers to Topbar dropdown menus
- Add data-shortcuts-disabled attribute support for WCAG 2.1.4 compliance
- Add screen-reader live regions to root layout for status/alert announcements
- Add accessibility E2E spec with axe-core violation checks
…cation, naming, suspicious-login warnings, and recovery escalation

- Add Device and Session domain models, repository methods, and in-memory store
- Create device service: register, rename, revoke, flag compromised, suspicious login detection
- Add TanStack Start API routes: GET /devices, GET /devices/recovery,
  GET /devices/:deviceId, PUT /devices/:deviceId/name,
  POST /devices/:deviceId/revoke, POST /devices/:deviceId/compromised,
  POST /sessions/:sessionId/revoke
- Expand audit log with device.registered, device.renamed, device.revoked,
  device.trust_toggled, device.key_rotated, device.recovery_activated,
  device.suspicious_login events (all security category, no sensitive body content)
- Build device management UI in Security settings tab:
  - Current device identification banner
  - Device list with key status badges (active/compromised/revoked/rotated)
  - Relative time formatting for last activity
  - Inline device renaming
  - Revoke with detailed consequence explanation
  - Compromised device flagging with immediate session invalidation
  - Suspicious login alert banner for compromised devices
  - Revocation consequences info panel
  - Account recovery status with device/trusted counts
  - Encryption key display with rotation confirmation dialog
  - Confirmation dialog with contextual styling (danger/warning/info)
- Audit history explicitly excludes message body content
@Timrossid Timrossid force-pushed the feature/device-management branch from 3fb8294 to d586129 Compare June 17, 2026 18:41
Timrossid and others added 11 commits June 17, 2026 20:02
…, key rotation, trust toggling, and API integration

Backend improvements:
- Add RecoveryMethod domain model, repository, service, and API routes (CRUD)
- Add device registration endpoint (POST /devices/register)
- Add key rotation endpoint (POST /devices/rotate-keys)
- Add trust toggling endpoint (POST /devices/:id/trust)
- Expand device service with: toggleDeviceTrust, rotateDeviceKeys,
  createRecoveryMethod, deleteRecoveryMethod
- Improve registerDevice to reject revoked/compromised device re-registration
- Add OpenAPI documentation for all 11 new device/session endpoints
- Add 19 comprehensive unit tests covering all device service functions

Frontend overhaul:
- Wire up useDevices hook to real API calls via apiFetch helper
- Add error banner, toast notifications (sonner), and dismissable errors
- Add security alert banner with pulsing icon for compromised devices
- Add warning banner for revoked devices
- Add recovery methods management UI (add with type-selector form,
  list with icons, remove with confirmation)
- Add inline trust toggling button for each device (visual feedback)
- Add key rotation with confirmation dialog and loading state
- Add device registration prompt when no devices exist
- Add spinner and disabled state during confirmation actions
- Show active key count, device status info on revoked/compromised cards
- Update RecoveryStatus type to include recoveryMethods array
- AudienceSegmentEditor: add htmlFor + id to associate labels with controls
- PersonaPicker: add Escape key handler to dialog backdrop
- policy-editor/route: change <label> to <span> (not form controls)
- DealLeadMailTracker: remove unnecessary tabIndex on li items
- SharedDraftList/WatchlistList: remove redundant role='list'/'listitem'
- payment-approval-form: add eslint-disable for form keydown handler
- payment-approval-list: move aria-sort from button to th
- migrations: remove unused eslint-disable directive
@kryputh

kryputh commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

@Timrossid \fix \cl

Timrossid and others added 2 commits June 19, 2026 00:24
…ement

- Fix prettier syntax error in Sidebar.tsx (removed duplicate nested <nav>)
- Add missing IdempotencyRecord interface to domain.ts
- Add missing idempotency Map field to MemoryApiRepository
- Add IdempotencyRecord import to repository.ts and memory-repository.ts
- Fix undefined hasUnread reference in SettingsModal (import useChangelog)
- Clear idempotency map in memory repository reset()

These fixes resolve the failing CI checks for the device management feature.
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.

client: add device and session security management

2 participants