Device Pairing
Online pairing is the default way to add a device to an initialized vault. It uses the same signed invite, join request, acceptance, and membership checks as the file transport, with encrypted envelopes relayed through a short-lived HTTP session.
Online Flow
Section titled “Online Flow”Both devices must already have the vault configured and their Lattice daemons running. On the current membership owner:
lattice vault invite personalThe CLI uses https://pair.latticepm.net by default for a 10-minute session,
renders a QR code when standard output is an interactive terminal with enough
width, and always prints the canonical LPM1-... pairing code. The QR payload
is exactly that same code, so it can be scanned, read from the terminal, or
delivered manually without changing the protocol.
On the joining device:
lattice vault joinEnter the LPM1-... code at the hidden prompt. The joining device fetches and
decrypts the invite, creates its signed join request, and prints a confirmation
code. The owner prints the same confirmation code after receiving that request.
Compare this second code over an independent channel and approve the owner’s
default-no prompt only when both values match.
After approval, the joining device verifies and applies the signed acceptance, then deletes the rendezvous session. Expired sessions are unavailable and garbage-collected by the server. Interrupted attempts can resume while the session and local pending state remain valid.
The pairing capability and confirmation code serve different purposes:
- The
LPM1-...value locates the session and derives its encryption keys. It is a secret capability even though it is designed for manual entry. - The confirmation code binds the actual invite and joining device keys. Its out-of-band comparison detects a substituted join request before membership is changed.
Use --role helper on the owner command to add a helper instead of the default
writer:
lattice vault invite personal --role helperAlternate Server And Code Files
Section titled “Alternate Server And Code Files”Select a different rendezvous on both devices with an HTTPS URL:
lattice vault invite personal --server https://pairing.example.netlattice vault join --server https://pairing.example.netPlain HTTP is accepted only for a loopback server, which supports local testing and a same-host reverse proxy. Redirects are not followed.
--code-file <path> supplies the exact LPM1-... capability without putting
it on the command line or in shell history:
lattice vault invite personal --code-file /private/path/pairing-codelattice vault join --code-file /private/path/pairing-codeThe owner command normally generates the capability; with --code-file, it
uses the supplied value instead. Keep the file private, do not place it in a
synchronized directory, and remove it after the attempt. The option cannot be
combined with the file-based invite transport.
File Fallback
Section titled “File Fallback”When no HTTP rendezvous is available, transport the signed packages yourself:
# Ownerlattice vault invite personal --out personal.lattice-invite
# Joining devicelattice vault join personal.lattice-invite --out personal.lattice-join
# Owner, after comparing the confirmation code out of bandlattice vault invite approve personal personal.lattice-join \ --out personal.lattice-acceptance
# Joining devicelattice vault join accept personal.lattice-acceptanceThe files contain protocol packages rather than the LPM1-... capability. The
same signature, role, confirmation, membership, and package-size validation is
applied to both transports.
Rendezvous Trust Boundary
Section titled “Rendezvous Trust Boundary”The rendezvous receives a derived opaque session identifier, encrypted phase
envelopes, expiry metadata, sizes, timing, and ordinary network metadata. It
does not receive the LPM1-... capability, vault plaintext, membership
plaintext, or envelope keys. Envelope encryption and phase authentication use
keys derived from the pairing capability; the server is not a membership
authority.
Anyone who obtains the pairing capability before expiry can access that session, so the separate confirmation is mandatory. The service also needs normal public-endpoint protections against traffic analysis, denial of service, and abusive session creation; encryption does not address those risks.
Self-Hosting
Section titled “Self-Hosting”The backend runs as a foreground service:
lattice pairing-rendezvous config-check \ --config packaging/lattice-pairing-rendezvous.tomllattice pairing-rendezvous run \ --config packaging/lattice-pairing-rendezvous.tomlThe packaged config listens on 127.0.0.1:4211, limits sessions to 10 minutes,
and exposes /healthz and /readyz on that private listener. Place a TLS reverse
proxy in front of /v1/sessions/*; do not expose port 4211 or the probe routes
directly. System and per-user systemd units, installation commands, state paths,
and readiness checks are documented in Self-Hosted Availability
Profile.
The repository provides the backend and packaging but does not deploy
https://pair.latticepm.net, its DNS, certificate, or reverse proxy.
Serverless Backend
Section titled “Serverless Backend”An equivalent backend for Cloudflare Workers and Durable Objects is in
serverless/pairing-rendezvous. It serves the same routes, statuses, headers,
TTL, phase ordering, idempotency, and quotas, so clients select it with the same
--server option and require no protocol change. The worker owns a hostname
rooted at /; the packaged route binds pair.latticepm.net, which is also the
client default. Build, test, and deploy procedures are in
serverless/pairing-rendezvous/README.md.