Invite codes and device pairing
Invite codes and device pairing
Status: Delivered
CAS: CAS-583
Delivered: 2026-04-25
PRs: #188 (F1 invite generation UI), #190 (F1–B3 invite backend + deep-link redemption)
What’s new
Casaconomy now supports a cryptographically secure invite system for adding a second device to an existing vault (device pairing) and for joining an existing group as a new participant. Invites are short alphanumeric codes generated on the issuing device and accepted on the new device — the relay that carries them can never synthesize or replay one.
How to use it
Generating an invite (issuer side):
- Open the invite screen and tap Generate invite.
- The app displays a short Crockford-Base32 code and a deep link QR code.
- The invite is valid for a limited window; the expiry is shown on screen.
- Share the code or QR with the person or device joining.
- The code can be cancelled at any time before it is redeemed.
Accepting an invite (acceptor side):
- On the new device, open the deep link or manually enter the invite code.
- The app verifies the issuer’s signature, performs an X25519 ECDH handshake, and derives a shared session key via HKDF-SHA256.
- The issuer sends an encrypted identity bundle (XSalsa20-Poly1305 AEAD) over the WebSocket relay channel.
- On successful decryption, all keys are persisted to the acceptor’s keystore and the device is fully paired — no further manual steps required.
What changed under the hood
- InviteCode type — new domain type with a Crockford-Base32 codec that avoids ambiguous characters (I/1, O/0).
- Relay integration —
POST /invites/{code}to publish andGET /invites/{code}to claim; the relay is treated as an untrusted message bus and never sees plaintext. services/invite_service.rs— core of the device-pairing protocol:- Issuer path (
invite_device_start): generates ephemeral X25519 keypair, signs an invite manifest with the device’s long-term Ed25519 key, publishes to relay, then waits over WebSocket for the acceptor’s ephemeral key to complete the ECDH. - Acceptor path (
invite_device_accept): fetches and verifies the signed manifest, sends its own ephemeral key, derives the HKDF session key, decrypts the identity bundle, and imports the keys into the local keystore.
- Issuer path (
- New Tauri commands —
invite_device_start,invite_device_cancel,invite_device_accept; progress reported on theinvite://progressevent channel. encryption/keystore.rs— addedimport_symmetric_keyandimport_signing_keypairfor the acceptor to persist received key material.- Invite generation UI — new screen with code display, QR code, expiry countdown, and cancel action.
- Deep-link handler —
casaconomy://invite/{code}URL scheme routes the acceptor into the redemption flow with the code pre-filled.
Why we built it
Without a secure pairing mechanism, adding a second device or new group member requires manual key export and import — error-prone and opaque to non-technical users. The invite code system makes onboarding a second device a single short-code exchange while keeping the relay server completely blind to the key material it carries. This is the foundational prerequisite for the full multi-device onboarding flow (CAS-149).
Known limitations / follow-on work
- End-to-end smoke test across two local app instances is deferred to CAS-591.
- Group join flow (Flow B — new user joining an existing group) shares the same transport but uses a different key exchange; the UI for that path is not yet wired up.
- The relay is currently a Cloudflare Worker; failover and rate-limiting are not yet hardened for production traffic.
- Deep-link handling requires
casaconomy://URL scheme to be registered on the OS; this is only tested on macOS so far.