Skip to content

feat(trust): add fileless device pairing - #45

Merged
sanchxt merged 9 commits into
sanchxt:mainfrom
shideneyu:feat/trust-pairing
May 25, 2026
Merged

feat(trust): add fileless device pairing#45
sanchxt merged 9 commits into
sanchxt:mainfrom
shideneyu:feat/trust-pairing

Conversation

@shideneyu

Copy link
Copy Markdown
Contributor

Summary

Add an experimental fileless trust pairing flow.

Today, the first trust relationship between two devices usually has to be created as a side effect of a file or clipboard transfer. This PR adds a dedicated yoop trust pair flow so devices can exchange
trusted identities without transferring user content.

This is intended as a proof of concept and needs more real-world testing before being considered fully polished.

What It Adds

  • yoop trust pair --listen to wait for an incoming pairing request.
  • yoop trust pair --host IP[:PORT] to pair directly with a known address.
  • yoop trust pair to scan for pairing listeners on LAN and Tailscale.
  • A lightweight pairing protocol that exchanges signed Ed25519 identities.
  • Trust-store creation with the peer address saved for future --device connections.

Notes

This is still a POC. The main flow works locally, but it should be tested more across:

  • LAN discovery
  • Tailscale peers
  • Linux/macOS combinations
  • custom ports and firewall setups
  • UX around prompts and rejected pairings

Validation

  • cargo fmt --all -- --check
  • cargo check -p yoop-core
  • Local smoke test with yoop trust pair --listen
  • Local smoke test with yoop trust pair --host
  • Local smoke test with scan-based pairing

@sanchxt

sanchxt commented May 7, 2026

Copy link
Copy Markdown
Owner

This PR is downgrading the version from 0.2.0, I'd appreciate if you could revert this change.

The pairing listener can be blocked indefinitely by a client that connects and then never sends PairingAck: wait_for_peer() awaits read_frame() without a timeout after sending PairingHello. Can we add a bounded timeout around the ack/result reads, or handle accepted connections in bounded per-connection tasks?

yoop trust pair --json in scan mode only emits candidates and returns, while the non JSON scan path proceeds to select and pair. Maybe we could unify the two, let me know if help is needed here!!

@shideneyu

Copy link
Copy Markdown
Contributor Author

Addressed in 9a2024a.

Changes:

  • Restored the workspace/package versions to 0.2.0.
  • Added bounded 30s timeouts around pairing TCP/TLS handshakes and pairing frame reads.
  • Updated JSON scan mode so it continues pairing when exactly one candidate is found.
  • If JSON scan finds multiple candidates, it now emits selection_required and asks the caller to use interactive mode or --host IP:PORT.

Validation:

  • cargo check -p yoop-core
  • cargo check -p yoop
  • cargo test -p yoop-core
  • cargo test -p yoop
  • cargo fmt --all -- --check

@sanchxt

sanchxt commented May 11, 2026

Copy link
Copy Markdown
Owner

Thanks for the follow up. I found two remaining CLI behavior issues before merge:

  1. yoop trust pair --json can still emit interactive prompts and block automation. In scan mode, if exactly one candidate is found, it proceeds into pair_with_address(), which still calls prompt_yes_no() / choose_trust_level() unless --yes is also passed. That means stdout is no longer JSON only and machine callers can hang.

  2. --level is ignored unless --yes is passed. choose_trust_level(level, yes) only parses the supplied level in the yes path, so yoop trust pair --host ... --level ask can still prompt and default to Full.

Can you make JSON mode non-interactive/JSON-only, and make --level honored independently of --yes?

Also, there's a CI test failing. I fixed it in #44 , you can take a look and fix it in this PR as well.

@shideneyu

Copy link
Copy Markdown
Contributor Author

Thanks, those two commits should fix it :

Changes:

  • Cherry-picked the CI/clippy fixes from fix(clipboard): avoid sync event backpressure #44.
  • Made yoop trust pair --json non-interactive:
    • JSON mode no longer calls prompt_yes_no().
    • JSON mode no longer calls the interactive trust-level prompt.
    • For JSON/non-interactive mode, the trust level defaults to full unless --level is provided.
  • Made --level honored independently of --yes, so --level ask now stores AskEachTime even
    without --yes.
  • Added focused tests for explicit --level ask and non-interactive default trust level.

@sanchxt
sanchxt merged commit 655463c into sanchxt:main May 25, 2026
11 checks passed
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.

2 participants