Koder Pair — peer-to-peer device pairing handshake
Protocolo de handshake para pareamento peer-to-peer entre dispositivos do mesmo dono na Koder Stack (Kode CLI, Kanvas, Talk, Drive, etc.). Define discovery via mDNS/bluetooth, key exchange (Noise XX), confirmação visual cross-device e armazenamento da relação no Koder Keys.
Spec — Koder Pair: peertopeer device pairing handshake
*tatus:*Normative (Draft) *pplies to:*engines/sdk/koder_pair_kit/, products/horizontal/pair/, any Koder app that wires same-owner device pairing (Kode CLI, Kanvas, future). *rigin:*KSTACK34 (OpenClaw analysis 202604-29). *rypto reuse:*Noise Protocol Framework — same primitives as products/horizontal/talk (RFC-001 QUIC transport). Do NOT introduce new cryptographic primitives.
1. Scope
This spec defines the *andshake*that establishes a Koder Pair session between two devices owned by the same human (e.g. desktop ↔ phone). Once established, the session reuses the Talk transport (Noise-encrypted streams over QUIC).
*ut of scope:*application-level message formats (Pair owns one per app: audio relay, notification mirror, co-pilot). Each consumer defines its own protobuf on top of the Pair session.
2. Pairing Modes
Two modes, both producing the same end state:
2.1 QR + Outofband
Default for casual setups (phone ↔ laptop in the same room).
- Initiator (e.g. desktop) calls
pair.PrepareInvite()→ returns:pair_token: 256-bit random, expires in 5 minutesinitiator_pubkey: Ed25519 public keyendpoint:host:portreachable on LAN, plus optionalrelay_urlfor crossnetwork pairing via Koder Hubhosted relay (see §5)
- Initiator displays a QR encoding
pair://{token}@{endpoint}?pk={pk_b64}. - Responder scans the QR with the Pair app, calls
pair.JoinInvite(uri). - Responder generates its Ed25519 keypair, opens a Noise XX handshake
over QUIC to
endpoint, presentspair_tokenin the handshake prologue. - Initiator verifies token, completes Noise XX, returns its long-term
identity in the final handshake message.
- Both sides write the peer's identity to local keystore — future
sessions skip the QR step (use Noise IK directly).
2.2 PIN fallback
When the QR camera is unusable (server pairing, wearable, accessibility):
- Initiator calls
pair.PreparePIN()→ returns:- 6-digit human PIN (displayed)
pair_token(same as 2.1)
- Responder enters PIN manually; SDK derives
pair_tokenfrom PIN +shared discovery channel context (so PINs alone don't authorize — the discovery channel proximity is part of the proof).
PIN mode requires both devices on the same LAN OR both authenticated to the same Koder ID v2 account (the relay validates both auth tokens).
3. Cryptographic Choices
| Property | Value |
|---|---|
| Identity keys | Ed25519 (matches Talk) |
| Handshake | Noise XX (mutual auth, forward secrecy) |
| Session keys | Derived via Noise XX → ChaCha20-Poly1305 |
| Transport | QUIC (matches Talk RFC-001) |
| Identity persistence | Per-device keystore via OS keychain (Keychain on macOS, Secret Service on Linux, Credential Manager on Windows, KeyStore on Android, Keychain on iOS) |
Reuses every primitive from `productshorizontaltalk/RFC001` — no new crypto reviewed. New auditing surface is limited to the prologue (token+PIN handling).
4. Session Lifetime
- Each Pair session is *er
devicepair* not per-app. Multiple Koderapps share the same underlying Noise session via the Pair daemon.
- Session is *ersistent*across restarts (re-handshake on first
message after reboot using cached identities — Noise IK pattern).
- *evocation:*the user can revoke a paired peer in any Koder app's
Settings → Paired Devices. Revocation broadcasts a tombstone via the Hub-hosted relay (see §5) so all this user's devices update their trust list.
5. Relay (cross-network pairing)
When devices aren't on the same LAN, the Hub hosts a thin relay at pair.koder.dev/relay:
- Initiator and Responder both authenticate to the relay with their
Koder ID v2 token (so the relay can confirm same-owner).
- Relay forwards Noise frames byte
forbyte; *ever decrypts*(it has no key material).
- Relay is rate-limited per Koder ID account (10 active sessions, 100
pairings/day).
6. Validation
- Smoke test: pair desktop+phone via QR; verify
kode device listshows both; revoke from desktop; verify phone no longer in the list.
- Property test: handshake with corrupted
pair_tokenMUST fail beforeany session key derivation.
- Audit: cryptographic review limited to §2 prologue handling — Noise
primitives below are inherited from Talk and don't need re-audit.
7. Non-Goals
- Multi
user mesh. Pair is for *ameowner*device sets only. Talkhandles multi-user.
- File transfer protocol. Pair sessions carry app-specific protobuf
streams; large transfers ride on top via app-level chunking.
8. References
products/horizontal/talk/docs/rfcs/RFC-001-quic-transport.md— Noise + QUIC stack inheritedservices/foundation/id— Koder ID v2 auth used by §5 relayengines/sdk/koder_pair_kit/docs/rfcs/RFC-001-pair-architecture.md— implementation spec