RFC-001 — koder_pair_kit: SDK architecture
Author: Koder Engineering Date: 2026-04-29 Status: Accepted Module: enginessdkkoderpairkit + productshorizontalpair Origin: koder-stack ticket #034 (OpenClaw analysis 2026-04-29) Spec: meta/docs/stack/specs/pair/handshake.kmd
1. Summary
A peer-to-peer pairing SDK + flagship Pair app for binding multiple devices owned by the same human into a single Kode session — desktop ↔ phone ↔ tablet ↔ Koder Konsul-equipped headset, etc. Reuses the Talk crypto stack (Noise + QUIC) so we add zero new audit surface.
Engine + product split per project memory engine_product_pattern remains optional here — Pair could ship as a standalone app or as a screen inside Kode. We adopt the standalone app path (§7).
2. Problem
OpenClaw ships a "node" model where the desktop assistant federates with mobile devices: the phone is a roaming microphone, a notification mirror, a co-pilot screen for long-running tasks. Today the Koder Stack has Talk (between people) and Kode (single-device sessions) but nothing bridges devices of one owner.
3. Goals
- Pairing once, session for life. QR or PIN at first contact;
Noise IK rehandshake automatically on every reconnect.
- One SDK consumed by Kode, Kanvas, Pass, future apps. They open
Pair sessions; Pair handles transport + identity + presence.
- Cross-platform: Flutter (mobile + desktop) for the SDK + app;
Go binding for backend tools; KL binding for
kodeCLI. - Cross-network via thin relay at
pair.koder.dev/relay(§5 ofthe spec) — never decrypted, just forwards Noise frames.
4. Non-Goals
- Multi-user mesh — that's Talk's job.
- File-transfer protocol — Pair carries app-defined protobuf; chunking
rides on top.
- Synchronous co-presence (Google Docs-style cursors) — out of v1.
5. Architecture
┌────────────┐ ┌────────────┐
│ Kode CLI │ │ Kanvas │
│ (desktop) │ ┌──────────┐ │ (mobile) │
└─────┬──────┘ │ Pair │ └─────┬──────┘
│ │ App │ │
└─via SDK→│ (UI for │←via SDK┘
│ user) │
└──┬───────┘
│
┌────────┴─────────┐
│ koder_pair_kit │
│ (SDK — Flutter, │
│ Go, KL) │
└────────┬─────────┘
│ Noise XX/IK
┌──────────┼──────────┐
│ │ │
LAN QUIC Hub Relay LAN QUIC
│
pair.koder.dev
(Hub-hosted, never decrypts)The SDK is the canonical surface; the Pair app is the human-facing front-end (QR scanner, paired-devices list, revocation UI). All session state lives in the SDK; the app is mostly a view.
6. SDK Surface
Dart (enginessdkkoderpairkit)
final pair = KoderPair();
final invite = await pair.prepareInvite(); // QR-bound
print('show: ${invite.qrUri}'); // pair://...
final remote = await pair.joinInvite(qrUri); // on the responder
remote.send(myProtobufBytes); // app-defined payload
remote.messages.listen((msg) => handle(msg));Go (enginessdkgo-koder-pair-kit) — future
Same shape; consumed by Kode CLI and any backend tool that wants to participate in a Pair mesh.
KL (engineslangkodarpairkit) — future
Native KL binding for kode CLI.
7. Standalone App vs Kode Screen
Decision: ship Pair as a standalone app (products/horizontal/pair/).
Rationale:
- Discoverability: users who want to pair their phone don't already
have Kode mobile installed. A purpose-built Pair app downloads from the Hub independently.
- Surface area: the QR scanner + paired-device list is enough UI
to merit its own product.
- Sub-feature in other apps: Kode and Kanvas import the SDK and
expose "Pair a device" entry points; users follow them to the Pair app for the actual flow.
8. Scope of Change
meta/docs/stack/specs/pair/handshake.kmd— handshake spec (landed)engines/sdk/koder_pair_kit/— Dart SDK (this RFC + scaffold)products/horizontal/pair/— Flutter app (scaffold + landing)- Future: Go and KL bindings; Kode integration (
kode pair add,kode device list) - Future: Hub relay (
pair.koder.dev/relay) — separate ticket
9. Execution Plan
| Phase | Deliverable |
|---|---|
| F1 | Spec + this RFC + scaffolds (DONE) |
| F2 | Dart SDK: Noise XX over QUIC (delegate to Talk's transport) |
| F3 | Pair app v0.1: QR generate + scan + paired-device list |
| F4 | Hub relay endpoint pair.koder.dev/relay |
| F5 | Kode integration (kode pair add, kode device list) |
| F6 | Cross-app demo: phone microphone → Kode desktop session |
| F7 | Go + KL bindings |
10. Alternatives Considered
- Skip Pair entirely; users open Talk between two of their devices.
Rejected: Talk's UX is multi-user mesh — bloated for the same-owner case. Pairing semantics, revocation, and discovery differ.
- Build Pair as a Kode-only screen. Rejected per §7.
- Use WebRTC instead of Noise+QUIC. Rejected: would introduce a
separate crypto stack to audit, contradicting the spec §3 "no new primitives" goal.
11. References
meta/docs/stack/specs/pair/handshake.kmd— handshake detailsproducts/horizontal/talk/docs/rfcs/RFC-001-quic-transport.md— transport stack inherited- Memory
koder_talk— Talk module status and crypto choices - Memory
engine_product_pattern— engine+product split convention(Pair is SDK+app, not engine+product, because Pair is not a multi-tenant service)