Files
rdp-proxy/docs/architecture/SERVICE_ADAPTER_PROTOCOL.md
T
2026-04-28 22:29:50 +03:00

212 lines
7.8 KiB
Markdown

# Service Adapter Protocol
Status: target contract and compile-safe foundation. This document defines the common adapter model for RDP, SSH, VNC, and future services. It does not replace the current backend control plane or current RDP runtime by itself.
## 1. Purpose
The platform client must not implement third-party protocols directly.
```text
Access Client <-> Secure Access Session Protocol <-> Service Adapter <-> Target Resource Protocol
```
A `Service Adapter` translates one external service protocol into the platform session/data-plane model. RDP is the first adapter, but the same model must support SSH, VNC, HTTP/internal apps, video, and future services.
## 2. Terms
- `Access Client`: user-facing Windows, iOS, Android, or future browser/native client.
- `Service Adapter`: protocol translation runtime at the service/egress edge.
- `RDP Adapter`: Service Adapter for Microsoft RDP.
- `SSH Adapter`: Service Adapter for SSH/terminal/SFTP/port-forward flows.
- `VNC Adapter`: Service Adapter for VNC framebuffer/input flows.
- `Target Resource`: external resource such as RDP host, SSH host, VNC host, internal app, or video endpoint.
- `Control Plane`: backend/API for auth, organization isolation, resource policy, session lifecycle, worker selection, audit, and token issuance.
- `Data Plane`: realtime channels between Access Client and adapter.
## 2.1 Remote Server/Desktop Access Product Model
The user-facing product service is **Remote Server/Desktop Access**.
RDP, VNC, and SSH are not separate cluster services exposed to organization
administrators. They are internal protocol adapters used by the Remote
Server/Desktop Access service.
The protocol is selected from the organization resource definition:
```text
Organization resource:
name: Accounting-01
address: 10.10.1.15
port: 3389
protocol: rdp
egress: Office Moscow
```
```text
protocol = rdp -> RDP Adapter
protocol = vnc -> VNC Adapter
protocol = ssh -> SSH Adapter
```
The Access Client always speaks the platform access protocol. It does not speak
RDP, VNC, or SSH directly.
Cluster operators assign nodes to run the Remote Server/Desktop Access service.
They do not separately enable "RDP service", "VNC service", or "SSH service" for
the organization. Adapter selection is an internal runtime decision based on the
selected resource protocol.
Organization administrators manage resources and policies, not internal nodes:
- resource name
- target address and port
- protocol
- allowed users/groups
- clipboard/file/session policy
- logical egress, such as `Office Moscow`
The logical egress is not a concrete node. It is an organization-visible egress
pool or route label. Internally the cluster may back `Office Moscow` with one or
many nodes that have network reachability to that office. Fabric routing and
placement choose the concrete node/path.
Resulting flow:
```text
Access Client
-> entry point
-> authenticate user
-> select organization
-> list allowed resources
-> select resource
-> use resource.protocol to choose adapter
-> use resource.egress to choose egress pool/path
-> connect to target
```
This decision prevents exposing internal adapter placement and node topology to
organizations while preserving protocol-specific policy enforcement inside the
adapter runtime.
## 3. Non-Negotiable Boundaries
- Access Client does not know RDP/SSH/VNC protocol internals.
- Service Adapter does not know UI implementation details.
- Control Plane remains authoritative for session lifecycle and policy.
- PostgreSQL remains source of truth; Redis remains live coordination only.
- Direct worker WSS and backend gateway fallback remain valid transports.
- Adapter runtime must not create sessions outside broker/assignment control.
## 4. Logical Channels
The session protocol is channel-oriented even when DP-1 uses one WSS connection.
| Channel | Direction | Reliability | Priority | Purpose |
| --- | --- | --- | --- | --- |
| `input` | client -> adapter | ordered reliable except move coalescing | highest | keyboard, pointer, wheel, focus |
| `control` | both | reliable | high | attach, detach, takeover, state, heartbeat |
| `display` | adapter -> client | droppable latest-frame/region | high but below input | frames, regions, surfaces, resize |
| `cursor` | adapter -> client | latest-only | high | cursor position, shape, visibility |
| `clipboard` | both | reliable | medium | policy-gated clipboard payloads |
| `file_transfer` | both | reliable chunked | medium/low | upload/download, progress, cancel |
| `audio` | adapter -> client, future client -> adapter | adaptive droppable | medium | future audio streams |
| `device` | both | reliable | medium | future printer, smart card, drive policy events |
| `telemetry` | adapter -> client/control | droppable | lowest | FPS, latency, queue depth, diagnostics |
Input must never wait behind display, file transfer, audio, or telemetry.
## 5. Event Direction Model
The adapter is not a passive responder. It must publish events whenever the target protocol emits them.
Client-origin examples:
- `input.keyboard`
- `input.pointer_move`
- `input.pointer_button`
- `input.wheel`
- `clipboard.client_text`
- `file_upload.start`
- `file_upload.chunk`
- `control.detach`
- `control.terminate`
Adapter-origin examples:
- `session.state`
- `display.full_frame`
- `display.region`
- `display.surface_bits`
- `display.encoded_frame`
- `cursor.update`
- `clipboard.server_text`
- `file_transfer.progress`
- `session.warning`
- `session.failed`
Screen updates must be adapter-driven:
```text
Target resource update -> adapter callback/event -> display/cursor event -> Access Client render
```
Client input may request a fast refresh, but input must not be the primary trigger for discovering server-side screen changes.
## 6. Channel Scheduling
The adapter runtime must maintain separate scheduling semantics:
- `input`: drain first; keyboard and button events are ordered; pointer move is latest-only.
- `control`: reliable and bounded; never behind render backlog.
- `display`: droppable; stale frames/regions are discarded before send.
- `cursor`: latest-only; may bypass display frame cadence.
- `clipboard`: reliable and policy-gated.
- `file_transfer`: reliable chunked; bandwidth-limited so it cannot starve input/display control.
- `telemetry`: sampled/dropped under pressure.
## 7. Render Model
Display events should be sent in this preference order:
1. Encoded/surface updates when supported by the external protocol and client.
2. Dirty regions/tiles.
3. Full frame only for baseline, resize, attach/recover, or fallback.
Full-frame BGRA is a compatibility fallback, not the production performance target.
## 8. Adapter Policy Enforcement
Policy must be enforced inside the adapter runtime in addition to UI/backend checks:
- clipboard mode
- file transfer mode
- allowed channels
- attachment/controller ownership
- session active/taken_over/failed/terminated state
- max payload sizes
- dangerous path/name rejection
- no arbitrary filesystem exposure
## 9. Adapter Lifecycle
All adapters must support:
- bind to existing assignment/session runtime
- connect to target resource
- publish state changes
- keep runtime alive through detach when policy allows
- reattach without recreating target session where protocol allows
- takeover without recreating target session where protocol allows
- terminate target session when broker commands terminate
- fail fast and report authoritative failure when target runtime is gone
## 10. Future Adapters
RDP, SSH, and VNC share the same platform-facing contract but differ internally:
- RDP: graphics, cursor, keyboard/mouse, cliprdr, rdpdr, rdpgfx/graphics pipeline.
- SSH: terminal output, keyboard input, resize, SFTP, port-forward.
- VNC: framebuffer updates, pointer, keyboard, clipboard.
The common contract is the platform session protocol, not the external resource protocol.