Skip to content

Mobile daemon connection wizard with manual entry + QR pairing #3344

Description

@houko

Part of Epic #3351 — mobile client support (iOS + Android via Tauri 2).

Problem

The desktop dashboard auto-discovers the local daemon at 127.0.0.1:4545. On mobile this assumption breaks: the daemon runs on the user's home server / VPS / NAS / desktop, the phone is on a different network, and there is no localhost to fall back to. Without an explicit connection wizard the mobile app cannot do anything on first launch.

Approach

A first-run wizard captures (base_url, api_key) and persists them in a platform-appropriate secure store. Three input methods, in order of effort:

  1. Manual entry — base URL + API key text inputs. Floor.
  2. QR pairing — desktop generates a one-time QR encoding {base_url, api_key, expires_at}; phone scans with the camera. Removes typing 64-char keys on a phone keyboard.
  3. mDNS / Bonjour discovery — when phone and daemon are on the same LAN, surface "Found daemon at homeserver.local" as a one-tap option. Nice-to-have, defer if integrating Tauri's mobile mDNS plugin is painful.

After connection: a connection-health screen showing daemon version, agent count, and a "Reconnect" button. If the daemon is unreachable on app foreground, surface a clear "offline" banner with a retry — do not silently fail.

Tasks

  1. New page connect/ in the dashboard with manual-entry form. Hide on desktop builds (cfg-gated render).
  2. Persist credentials via tauri-plugin-stronghold or tauri-plugin-keyring — whichever has the cleanest mobile story. Plain localStorage is unacceptable: API keys must not survive a backup-and-restore in clear text.
  3. QR generation in dashboard: new desktop-only route /settings/mobile-pairing that mints a short-lived (5 min) pairing token, signs it with the existing API key, and renders a QR. New API endpoint POST /api/pairing/tokens with TTL + single-use semantics.
  4. QR scanning on mobile: integrate tauri-plugin-barcode-scanner (or equivalent). Camera permission prompt copy must be explicit about "we read a one-time pairing code, not photos."
  5. Connection-health screen: pings /api/health, shows version + uptime + agent count from /api/agents. Re-pings on app_resume (Tauri lifecycle event).
  6. Offline banner: react-query onError falls into a top-level <OfflineBanner> with retry; auto-dismisses on next successful query.
  7. Logout path that clears the secure store and returns to the connect wizard.

Acceptance criteria

  • Mobile first launch: connect wizard appears, manual entry produces a working session.
  • API key stored in tauri-plugin-stronghold / tauri-plugin-keyring — verified by inspecting app sandbox, not in a plain JSON file.
  • QR pairing path: scan a desktop-generated QR, dashboard immediately becomes usable, no manual key entry required.
  • Pairing token endpoint enforces 5-minute TTL and single-use; re-using returns 410 Gone.
  • App-foreground re-checks connection health, surfaces banner if unreachable.
  • Logout clears the secure store and returns to connect wizard on next launch.
  • Desktop builds: /settings/mobile-pairing exists and renders a QR; the connect wizard route is hidden / never rendered (no regression).

mDNS discovery is out of scope for this issue; track as a follow-up after the manual + QR paths ship and have real users.

Depends on #3342. Runs in parallel with #3343.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/apiREST/WS endpoints and dashboardarea/desktopTauri desktop applicationdifficulty/mediumHalf day, some familiarity with the crateenhancementNew feature or requesthas-prA pull request has been linked to this issueneeds-triageAuto-applied when the issue title/body matched no area label — needs maintainer reviewseverity/lowMinor issue, polish, or developer ergonomics

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions