Skip to content

feat(cli): add ldgr devices command for QR/X25519 device onboarding#265

Merged
kafkade merged 1 commit into
mainfrom
kafkade-feat-cli-devices-command
Jul 7, 2026
Merged

feat(cli): add ldgr devices command for QR/X25519 device onboarding#265
kafkade merged 1 commit into
mainfrom
kafkade-feat-cli-devices-command

Conversation

@kafkade

@kafkade kafkade commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Description

Adds an ldgr devices command group that lets you pair a new device to your vault against a self-hosted ldgr-server, transferring the vault key end-to-end encrypted over the existing sync relay. This wires the already-implemented core onboarding crypto and server relay into an operator-facing CLI surface.

What's included

  • ldgr devices subcommands:
    • list — show the devices registered to your vault's account.
    • add — start a pairing session on an already-set-up device; renders a scannable QR code, a copy-paste token, and a verification code, then waits for the new device to join.
    • join <token> — complete onboarding on a new device (one that has already run ldgr sync setup); prints its own verification code and installs the received vault key.
    • remove <id> — deregister a device.
  • Transport-agnostic pairing orchestration in ldgr-core (sync::pairing): I/O-free per ADR-005, with the pairing token codec, an ECDH handshake, and zeroize-on-drop session state. All I/O (QR, prompts, poll loops, session storage) lives in the CLI.
  • End-to-end encrypted vault-key handoff: the key is AES-256-GCM encrypted under the X25519 ECDH shared secret, so the relay/server only ever sees ciphertext. Both devices display a matching verification code so a man-in-the-middle can be detected. No server changes were needed — the 3-message handoff is mapped onto the relay's 2-leg model via a two-offer handshake (both devices authenticate as the same account).
  • Docs: new "Pairing a new device" section in docs/sync-setup.md and a CHANGELOG.md entry.

iOS QR-scanning onboarding remains a planned follow-up; today join takes the token as an argument.

Related Issues

Closes #225

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Refactoring (no functional changes)
  • CI / infrastructure
  • Other (describe below)

Component

  • crates/ldgr-core/ — Core library (crypto, accounting, storage)
  • crates/ldgr-cli/ — CLI tool
  • crates/ldgr-server/ — Sync server
  • bindings/swift/ — UniFFI Swift bindings
  • apps/ios/ — iOS / iPadOS / watchOS app
  • apps/web/ — Web app (Next.js + WASM)
  • docs/ — Documentation

Privacy Checklist

  • No plaintext financial data is sent to or stored on the server
  • No new metadata exposure introduced (or documented if unavoidable)
  • Any new external service interaction is documented in the trust boundary model
  • Crypto changes use audited RustCrypto crates — no custom primitives
  • Key material is never exposed in error messages, logs, or Debug output

Checklist

  • I have read CONTRIBUTING.md
  • Tests pass (cargo test --workspace)
  • Clippy passes (cargo clippy --workspace -- -D warnings)
  • Formatting passes (cargo fmt --check)
  • I have updated documentation (if applicable)

Testing: adds crates/ldgr-server/tests/device_pairing_e2e.rs with two end-to-end tests proving (1) a joining device recovers the initiator's exact vault key over the encrypted relay and (2) device register/list/remove round-trips. Also adds unit tests for the pairing token codec in ldgr-core. Verified cargo test --workspace --all-features, cargo clippy --workspace --all-features --all-targets -- -D warnings, cargo fmt --check, and markdownlint-cli2 all pass.

CI note: no CI job names changed, so no kafkade/github-infra Terraform update is required.

@kafkade kafkade enabled auto-merge (squash) July 7, 2026 03:34
@kafkade kafkade merged commit 78c1fd4 into main Jul 7, 2026
14 checks passed
@kafkade kafkade deleted the kafkade-feat-cli-devices-command branch July 7, 2026 03:38
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.

feat(cli): ldgr devices command — QR/X25519 device onboarding surface

1 participant