Skip to content

Device & session security management (CI fixes)#877

Closed
Timrossid wants to merge 16 commits into
Stellar-Mail:mainfrom
Timrossid:fix/device-management-ci
Closed

Device & session security management (CI fixes)#877
Timrossid wants to merge 16 commits into
Stellar-Mail:mainfrom
Timrossid:fix/device-management-ci

Conversation

@Timrossid

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.

CI Fixes Included

  • Fixed prettier syntax error in Sidebar.tsx (unclosed nav element from a11y changes)
  • Added missing IdempotencyRecord type definition to domain.ts
  • Added missing idempotency Map field to MemoryApiRepository
  • Fixed missing IdempotencyRecord imports in repository files
  • Fixed undefined hasUnread reference in SettingsModal (added useChangelog import)
  • Added idempotency map cleanup in memory repository reset()

Acceptance Criteria

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

Closes #73

Timrossid and others added 16 commits June 17, 2026 19:02
…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
…, 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
…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.
@Timrossid

Copy link
Copy Markdown
Author

Closing in favor of PR #772 which has been updated with the same fixes.

@Timrossid Timrossid closed this Jun 19, 2026
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

1 participant