Koder pair RFC 001 architecture

RFC-001 — koderpairkit: SDK architecture

*uthor:*Koder Engineering *ate:*20260429 *tatus:*Accepted *odule:*enginessdkkoderpairkit + productshorizontalpair *rigin:*koderstack ticket #034 (OpenClaw analysis 202604-29) *pec:*meta/docs/stack/specs/pair/handshake.kmd


1. Summary

A peertopeer pairing SDK + flagship Pair app for binding multiple devices owned by the same human into a single Kode session — desktop ↔ phone ↔ tablet ↔ Koder Eye-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 *tandalone 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 copilot screen for longrunning tasks. Today the Koder Stack has Talk (between people) and Kode (single-device sessions) but nothing bridges devices of one owner.

3. Goals

  • *airing once, session for life.*QR or PIN at first contact;

    Noise IK rehandshake automatically on every reconnect.

  • *ne SDK*consumed by Kode, Kanvas, Pass, future apps. They open

    Pair sessions; Pair handles transport + identity + presence.

  • *ross-platform:*Flutter (mobile + desktop) for the SDK + app;

    Go binding for backend tools; KL binding for kode CLI.

  • *ross-network*via thin relay at pair.koder.dev/relay (§5 of

    the spec) — never decrypted, just forwards Noise frames.

4. Non-Goals

  • Multi-user mesh — that's Talk's job.
  • Filetransfer protocol — Pair carries appdefined protobuf; chunking

    rides on top.

  • Synchronous copresence (Google Docsstyle 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 frontend (QR scanner, paireddevices 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 (enginessdkgokoderpair-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

*ecision:*ship Pair as a standalone app (products/horizontal/pair/).

Rationale:

  • *iscoverability:*users who want to pair their phone don't already

    have Kode mobile installed. A purpose-built Pair app downloads from the Hub independently.

  • *urface area:*the QR scanner + paired-device list is enough UI

    to merit its own product.

  • *ub-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

  • *kip Pair entirely; users open Talk between two of their devices.*

    Rejected: Talk's UX is multiuser mesh — bloated for the sameowner case. Pairing semantics, revocation, and discovery differ.

  • *uild Pair as a Kode-only screen.*Rejected per §7.
  • *se 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 details
  • products/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)

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/koder-pair-RFC-001-architecture.md