KRDP — Koder Remote Desktop Protocol
remote specs/remote/krdp/protocol.kmd
The wire contract for Koder Pilot remote access: transport (QUIC / WebTransport / relay), the versioned capability handshake, the multiplexed channel set (video/input/clipboard/file/audio/device/control), codec carriage over engines/kodec, identity + connection-ID brokering (Koder ID + relay), the permission/consent model, and security. Faster-than-VNC by design (damage-tracked delta tiles + prioritized input with client-side prediction). Ratified by infra-RFC-008. Implemented by products/horizontal/pilot (backend + clients) and consumed by products/dev/grid (KRDP as a protocol alongside SSH/RDP/VNC).
When this spec applies
Primary triggers
- Implement or change the KRDP remote-access protocol
All triggers
- Implement or change the KRDP wire protocol (transport, channels, handshake)
- Add a KRDP channel or capability, or change a channel's framing/semantics
- Implement a KRDP host (Koder Pilot backend) or client (desktop/web/mobile/Grid)
- Change connection-ID brokering, permission prompts, or session security
Specification body
Spec — KRDP (Koder Remote Desktop Protocol)
KRDP is the wire contract a host (Koder Pilot backend / any KRDP agent) and a client (Koder Pilot desktop/web/mobile, or Koder Grid) speak to share and control a desktop/device. It is transport-framed, channel-multiplexed, and capability-negotiated, and it is designed to beat VNC on interactive latency.
Roles
- Host — the machine being viewed/controlled. Runs the KRDP server (Koder Pilot
backend/, as a service/daemon or an in-app session). Registers a connection ID. - Client — the machine viewing/controlling. Runs a KRDP client.
- Relay —
infra/net/remoterelay: NAT traversal + ID brokering + optional zero-knowledge forwarding. Never required on the LAN/direct path. - Broker — Koder ID (auth) + Koder DNS/registry (locate the host by ID), per
service-registry-contract.kmd+ infra-RFC-007. KRDP does not define its own identity plane.
R1 — Transport
R1.1 The native transport is QUIC (RFC 9000) over UDP, with TLS 1.3
mandatory, multiplexed bidirectional streams, and 0-RTT session resume.
R1.2 The web transport is WebTransport (HTTP/3) where available, falling
back to WebRTC DataChannel + SRTP — so a browser client needs no plugin.
R1.3 When direct/STUN fails (symmetric NAT both ends), peers fall back to the
Koder relay (TURN-like). The relay MAY be zero-knowledge (E2E keys, R6.3).
R1.4 Datagram (unreliable) flows MAY carry video/audio; reliable streams carry
input/clipboard/file/control. A client MUST tolerate either substrate.
R2 — Versioned capability handshake
R2.1 The first reliable stream is control; its first message is a Hello
carrying protocol = "krdp/<major>", the sender's offered capabilities, and a
nonce.
R2.2 Both peers negotiate the intersection of capabilities; a capability absent
from the intersection MUST NOT be used. Unknown capabilities are ignored, not
errors (forward-compat, always-on.kmd).
R2.3 The negotiated protocol major MUST satisfy the compat window of
always-on.kmd (host serves N, N-1, N-2). A client offering an unsupported major
gets a typed Unsupported close, never a silent drop.
R2.4 Capabilities are the channel names (R3) plus feature flags (e.g.
video.av1, input.prediction, device.usb, relay.e2e).
R3 — Channels
A session is a set of typed channels over the transport. The absence of a channel = the capability was not negotiated or not granted (R7).
| Channel | Substrate | Purpose |
|---|---|---|
control | reliable | Lifecycle, handshake, permission prompts, cursor shape, geometry, channel open/close. Always present. |
video | datagram-preferred | Encoded framebuffer (R4). Multi-monitor = one video stream per output. |
input | reliable, prioritized | Keyboard/mouse/touch/pen (R5). |
clipboard | reliable | Bidirectional copy/paste; text + image + file-list; consent + size-bounded. |
file | reliable | Browse + resumable, hash-verified transfer (R8). |
audio | datagram-preferred | Opus out (host→client) + optional mic in. |
device | reliable | Device forwarding/inventory (R9). |
R3.1 control MUST be open before any other channel.
R3.2 Each channel frame carries a channel id + monotonic sequence; a client MUST
detect and surface (not silently drop) an out-of-window sequence on a reliable
channel.
R4 — Video: damage-tracked delta tiles over kodec (the VNC speed gap)
R4.1 The host MUST encode via engines/kodec (hardware NVENC where present; SW
fallback). Negotiable codecs: H.264 (baseline mandatory), HEVC, AV1.
R4.2 The host MUST send damage-tracked delta tiles, not full frames, when only a
region changed. A full keyframe is sent on connect, on request, and on a bounded
interval for recovery.
R4.3 Bitrate MUST be adaptive: drop video quality first under congestion so
input (R5) never starves. On an input burst, the host MAY raise the keyframe
cadence for responsiveness.
R4.4 The codec/profile is chosen at handshake (R2.4) and MAY be renegotiated mid-
session (e.g., AV1 capability appears) without tearing down channels.
R5 — Input: prioritized, predicted, reconciled
R5.1 input is a reliable, prioritized stream — input MUST NOT queue behind
video. This is the headline interactivity property.
R5.2 Clients SHOULD apply client-side prediction (local cursor) and the host
reconciles authoritative state; the protocol carries a per-event client timestamp +
sequence for reconciliation.
R5.3 The flip gate for the self-hosted pair (#23) is request→applied input-RTT
strictly lower than a VNC baseline on the same link (measured per
stack-RFC-012's corpus). A KRDP host that cannot beat VNC fails g2_performance.
R5.4 Key/pointer events MUST be coalesced where lossless (e.g., mouse-move
batching) but never reordered.
R6 — Identity, connection-ID brokering, security
R6.1 A host is addressable by a human-readable connection ID (RustDesk-style
numeric/word ID, stable per install) and by its Koder ID (managed/fleet
devices). The ID + locate path reuses the registry (service-registry-contract.kmd)
- infra-RFC-007; KRDP defines no new identity store.
R6.2 A connect MUST be authorized by one of: a one-time session password
(attended), a persistent password (unattended opt-in), or a Koder ID grant
(managed). Default is one-time + attended.
R6.3 Transport security is TLS 1.3 / QUIC mandatory, per-session keys. E2E
mode (
relay.e2e) keeps the relay zero-knowledge. Per-service identity follows the mTLS PKI (RFC-009 when ratified). No plaintext/HTTP leg, ever (security.kmd). R6.4 Every connect, capability grant, and unattended session MUST be audited (observability-first.kmd); audit records carry tenant + host ID + client identity.
R7 — Permissions & consent
R7.1 Default-deny, least-privilege. The host grants capabilities per-channel;
an ungranted channel is never opened.
R7.2 Attended (consumer): the host shows a consent prompt naming the requesting
party with per-capability toggles (view-only / control / clipboard / file /
audio / device). The user MAY revoke any capability mid-session; revocation closes
that channel immediately.
R7.3 Unattended (managed, infra/net/remote#006): a persistent policy grants
capabilities ahead of time, fenced by a Koder ID per-device grant; the host still
records the session in the audit trail.
R7.4 Multi-tenant by default (multi-tenancy/contract.kmd): a host belongs to a
tenant; a cross-tenant connect MUST carry an explicit grant or be refused with a
typed error (no cross-tenant default-allow).
R8 — File & clipboard semantics
R8.1 file transfers MUST be resumable (offset + length) and hash-verified
(per-file digest) end to end.
R8.2 clipboard and file payloads MUST be size-bounded by a negotiated cap;
exceeding it is a typed error, never a silent truncation.
R8.3 Clipboard image/file-list sharing MUST be consent-gated (a capability under
R7), independent of the text clipboard.
R9 — Device channel (honest per-platform scoping)
R9.1 device covers, where the host OS permits: USB redirection, camera (v4l2,
infra/net/remote#007), printer, smartcard.
R9.2 HDMI, Bluetooth, Wi-Fi, and wired-network are exposed as capture /
inventory surfaces (read adapter state, capture an HDMI-in source, list/scan
adapters) — not raw bus tunneling where the OS/security model forbids it. The
host MUST advertise only the device capabilities it can actually honor on its
platform (no phantom capabilities at handshake).
Conformance
- Host —
products/horizontal/pilotbackend/(absorbsinfra/net/remoteagent #001 + relay #002): R1–R9. Tests (backend/tests/): handshake intersection (T-R2), video delta-tile + keyframe-on-request (T-R4), input priority under video congestion (T-R5.1), input-RTT-beats-VNC harness (T-R5.3), default-deny + per-capability grant/revoke (T-R7), resumable hashed file transfer (T-R8), per-platform device capability advertisement (T-R9.2). - Client —
products/horizontal/pilot/app/{desktop,web,mobile}: R1.x (its transport), R2, R3, R5.2 (prediction), R7.2 (consent UI). The web client MUST implement R1.2 (WebTransport/WebRTC). - Grid consumer —
products/dev/grid: R2, R3 (view + input + clipboard), R6.1 (connect by ID). Grid is a client; it need not implement the host rules.
Non-goals
- GPU/game streaming (Koder Beam, stack-RFC-010 — a different latency/quality profile).
- A shell/terminal protocol (SSH stays SSH; Grid keeps it).
- Raw USB/PCIe/BT tunneling where the OS forbids it (R9.2 scopes this honestly).
- Defining identity/registry mechanics (reuses Koder ID +
service-registry-contract.kmd).
References
meta/docs/stack/rfcs/infra-RFC-008-krdp-remote-access-protocol-and-module.kmdmeta/docs/stack/specs/discovery/service-registry-contract.kmdmeta/docs/stack/policies/self-hosted-first.kmdmeta/docs/stack/policies/always-on.kmdmeta/docs/stack/policies/security.kmdmeta/docs/stack/policies/multi-tenant-by-default.kmdmeta/docs/stack/specs/auth/oauth-flow.kmdengines/kodecproducts/horizontal/pilotproducts/dev/gridinfra/net/remote