Files
BetterDesk/docs/architecture/CDAP_IMPLEMENTATION_PLAN.md
2026-03-24 00:26:25 +01:00

41 KiB

CDAP Implementation Plan

Version: 1.0.0
Status: Draft
Created: 2026-03-19
Depends on: CUSTOM_DEVICE_API.md v0.2.0


Table of Contents

  1. Overview
  2. Architecture Decisions
  3. Authentication & 2FA Integration
  4. RustDesk Client Synchronization
  5. Implementation Phases
  6. File-Level Change Map
  7. Testing Strategy
  8. Migration & Backward Compatibility
  9. Risk Assessment

Overview

This document translates the CDAP specification (CUSTOM_DEVICE_API.md) into a concrete implementation plan covering:

  • CDAP Gateway — WebSocket server on port 21122 in Go server
  • Auth integration — CDAP clients authenticate via the same user/2FA system as the Node.js panel and RustDesk clients
  • RustDesk synchronization — CDAP native desktop clients coexist with RustDesk clients in the same peer table, address books, connection history, and panel views
  • Media channel — Binary frame relay for remote desktop, video, audio, input
  • Native BetterDesk client — Desktop agent that combines remote desktop + OS management

Core Principle

One identity, one authority. A user account created in the Node.js panel works for panel login, RustDesk client login, AND CDAP native client login — same credentials, same 2FA, same RBAC.


Architecture Decisions

AD-1: Auth Source of Truth

Decision: The Go server is the auth source of truth for all protocol-level authentication (RustDesk clients, CDAP clients, API keys). The Node.js panel is the auth source of truth for panel UI sessions (cookie-based).

Rationale: RustDesk clients already authenticate via Go server's /api/login (port 21114). CDAP clients will use the same endpoint or a CDAP-specific auth message that routes to the same Go auth backend. This avoids auth duplication and ensures 2FA state is consistent.

┌──────────────────────────────────────────────────────┐
│                 Authentication Flow                    │
│                                                        │
│  Panel User       → Node.js session (cookie)           │
│    └─ 2FA check   → Node.js auth.db (TOTP)            │
│                                                        │
│  RustDesk Client  → Go server /api/login (JWT)         │
│    └─ 2FA check   → Go server TOTP (5-min partial)    │
│                                                        │
│  CDAP Client      → Go server /ws/cdap auth msg (JWT)  │
│    └─ 2FA check   → Go server TOTP (same path)        │
│                                                        │
│  Panel ↔ Go       → X-API-Key header (.api_key file)  │
│                                                        │
│  ──── Shared ─────────────────────────────────────     │
│  Users table:   Go server db (users)                   │
│  TOTP secrets:  Go server db (users.totp_secret)       │
│  Roles/RBAC:    Go server db (users.role)              │
│  API keys:      Go server db (api_keys)                │
│  Panel sessions: Node.js auth.db (separate, UI only)   │
└──────────────────────────────────────────────────────┘

AD-2: Dual Auth Database Convergence

Current state: Node.js panel has auth.db (users, sessions) and Go server has db_v2.sqlite3 (users, api_keys). Both have user tables with potentially different passwords and TOTP states.

Decision: Phase 1 keeps dual DBs but syncs user credentials. Phase 3+ converges to Go server as sole user store, with Node.js panel delegating auth to Go server via REST API.

Phase Auth Model User Store
Current Dual (Node.js auth.db + Go users table) Both, may diverge
Phase 1 CDAP CDAP uses Go auth only Go server primary for clients
Phase 3 Node.js delegates to Go for user CRUD Go server sole source
Long term Single user store in Go, Node.js is pure UI Go server

AD-3: CDAP Auth Message vs HTTP Login

Decision: CDAP clients authenticate within the WebSocket connection using a JSON auth message (not a separate HTTP /api/login call). The Go server validates credentials using the same auth.VerifyPassword() and auth.ValidateTOTP() functions.

Rationale:

  • Single connection setup (no HTTP pre-auth + WS upgrade dance)
  • Works behind restrictive firewalls that only allow WS on one port
  • Consistent with the "one port, one protocol" CDAP philosophy
  • Server can immediately associate the WS connection with the authenticated user
// Step 1: Client sends auth message
{
  "type": "auth",
  "payload": {
    "method": "user_password",
    "username": "operator1",
    "password": "...",
    "device_id": "CDAP-A7F3B210",
    "client_version": "1.0.0"
  }
}

// Step 2a: Server responds (no 2FA)
{
  "type": "auth_result",
  "payload": {
    "success": true,
    "token": "jwt_24h",
    "role": "operator",
    "device_id": "CDAP-A7F3B210"
  }
}

// Step 2b: Server responds (2FA required)
{
  "type": "auth_result",
  "payload": {
    "success": false,
    "requires_2fa": true,
    "tfa_type": "totp",
    "partial_token": "jwt_5min"
  }
}

// Step 3: Client sends 2FA code
{
  "type": "auth_2fa",
  "payload": {
    "partial_token": "jwt_5min",
    "code": "123456"
  }
}

// Step 4: Server responds with full auth
{
  "type": "auth_result",
  "payload": {
    "success": true,
    "token": "jwt_24h",
    "role": "operator",
    "device_id": "CDAP-A7F3B210"
  }
}

// Alternative: API key auth (for unattended bridges/agents)
{
  "type": "auth",
  "payload": {
    "method": "api_key",
    "key": "...",
    "device_id": "CDAP-A7F3B210"
  }
}

AD-4: RustDesk Client Synchronization Strategy

Problem: When a BetterDesk native client (CDAP) runs on the same machine as a RustDesk client, or replaces it, the following must be synchronized:

Resource RustDesk Source CDAP Source Sync Strategy
Device ID Numeric (e.g., 1340238749) CDAP- prefix Map: Go server maintains cdap_peer_idrustdesk_peer_id
Address book /api/ab (Go server) Same /api/ab Shared: Same user, same AB
Connection history Audit log (conn events) Audit log (conn events) Shared: Same audit table
User account Go users table Same Shared: Same credentials
Peers list peers table Same peers table Shared: device_type column
Online status Signal server in-memory map CDAP gateway in-memory Merged: Panel queries both
Tags/Groups peers.tags Same Shared: Same field

AD-5: Native Client ↔ RustDesk Interoperability

Scenario: User A has BetterDesk native client. User B has RustDesk client. Can User A remote-control User B's machine?

Decision: Not directly — CDAP media channel is not compatible with RustDesk's protobuf signal/relay protocol. But the server can bridge the connection:

From → To Method Latency Status
RustDesk → RustDesk Native (signal/relay) Low Works now
CDAP → CDAP Native (CDAP media) Low Phase 5
CDAP → RustDesk Server-side protocol bridge Medium (+50ms) Phase 6
RustDesk → CDAP Not needed (CDAP is superset) Not planned

The server-side protocol bridge (Phase 6) is complex and optional. The primary migration path is: install BetterDesk native client → device appears as both rustdesk AND desktop types → gradually deprecate RustDesk client on that machine.

AD-6: Unified Device Identity

When a machine has both RustDesk and BetterDesk native clients:

┌─────────────────────────────────────────┐
│              Machine: PC-Design-03       │
│                                         │
│  ┌──────────────┐  ┌─────────────────┐  │
│  │ RustDesk      │  │ BetterDesk     │  │
│  │ Client        │  │ Native Client  │  │
│  │               │  │                │  │
│  │ ID: 892734561 │  │ ID: CDAP-D2E9F4│  │
│  │ Port: 21116   │  │ Port: 21122   │  │
│  └──────┬───────┘  └───────┬────────┘  │
│         │                   │           │
└─────────┼───────────────────┼───────────┘
          │                   │
          ▼                   ▼
┌───────────────────────────────────────┐
│           BetterDesk Server            │
│                                       │
│  peers table:                         │
│  ┌─────────────┬──────────┬─────────┐ │
│  │ 892734561   │ rustdesk │ linked  │ │
│  │ CDAP-D2E9F4 │ desktop  │ linked  │ │
│  └─────────────┴──────────┴─────────┘ │
│                                       │
│  peer_links table (NEW):              │
│  ┌──────────────┬───────────────────┐ │
│  │ 892734561    │ CDAP-D2E9F4      │ │
│  │ (rustdesk)   │ (desktop)        │ │
│  └──────────────┴───────────────────┘ │
│                                       │
│  Panel shows: 1 machine, 2 protocols  │
│  Admin can merge or keep separate     │
└───────────────────────────────────────┘

Authentication & 2FA Integration

CDAP Auth Flow (Detailed)

                             ┌──────────────┐
                             │  CDAP Client  │
                             │  (bridge/     │
                             │   agent)      │
                             └──────┬───────┘
                                    │
                           WS connect :21122
                                    │
                                    ▼
                            ┌───────────────┐
                            │ CDAP Gateway  │
                            │ (Go server)   │
                            └───────┬───────┘
                                    │
                    ┌───────────────┼───────────────┐
                    │               │               │
              method=api_key  method=user_password  method=device_token
                    │               │               │
                    ▼               ▼               ▼
             ┌──────────┐   ┌──────────┐   ┌──────────────┐
             │ Validate  │   │ Validate │   │ Validate     │
             │ API key   │   │ user/pass│   │ device token │
             │ (SHA256)  │   │ (PBKDF2) │   │ (enrollment) │
             └──────┬───┘   └──────┬───┘   └──────┬───────┘
                    │               │               │
                    │        ┌──────┴──────┐        │
                    │        │ TOTP check  │        │
                    │        │ if enabled  │        │
                    │        └──────┬──────┘        │
                    │               │               │
                    ▼               ▼               ▼
             ┌─────────────────────────────────────────┐
             │           Session established            │
             │  - JWT token issued (24h)               │
             │  - Role assigned (admin/operator/viewer) │
             │  - Device ID confirmed/assigned         │
             │  - WS connection upgraded to authed     │
             │  - Audit log: auth event                │
             └─────────────────────────────────────────┘

Auth Methods

Method Use Case 2FA Description
user_password Interactive (operator login on desktop) Yes (if enabled) Same credentials as panel login
api_key Unattended (IoT bridges, SCADA, headless) No API key from Go server api_keys table
device_token First-time enrollment No One-time enrollment token (becomes API key)

2FA for Native Desktop Client

The BetterDesk native desktop client needs a full 2FA UI:

┌──────────────────────────────────────┐
│       BetterDesk - Login             │
│                                      │
│  Server: betterdesk.example.com      │
│                                      │
│  Username: [operator1        ]       │
│  Password: [••••••••         ]       │
│                                      │
│  [Login]                             │
└──────────────────────────────────────┘
                │
        (server responds: requires_2fa)
                │
                ▼
┌──────────────────────────────────────┐
│       BetterDesk - 2FA               │
│                                      │
│  Enter authenticator code:           │
│                                      │
│  [1] [2] [3] [4] [5] [6]            │
│                                      │
│  ○ Use recovery code instead         │
│                                      │
│  [Verify]            [Cancel]        │
└──────────────────────────────────────┘
                │
        (verified → full session)
                │
                ▼
┌──────────────────────────────────────┐
│  ✓ Connected as operator1            │
│  Server: betterdesk.example.com      │
│  Device ID: CDAP-D2E9F4             │
│                                      │
│  This device is ready for remote     │
│  connections and management.         │
│                                      │
│  [Settings]  [Minimize to tray]      │
└──────────────────────────────────────┘

2FA Setup for CDAP Clients

CDAP clients do NOT set up 2FA themselves — 2FA is configured through the Node.js panel:

Panel (Node.js)                    Go Server                CDAP Client
     │                                │                         │
     │── POST /api/auth/totp/setup ──►│                         │
     │◄── {qrCode, secret} ──────────│                         │
     │                                │                         │
     │  (user scans QR in Authy)      │                         │
     │                                │                         │
     │── POST /api/auth/totp/enable ─►│                         │
     │   {code: "123456"}             │── update users table ──│
     │◄── {recoveryCodes} ───────────│                         │
     │                                │                         │
     │                                │      (next login)       │
     │                                │◄── auth {user/pass} ───│
     │                                │──► auth_result          │
     │                                │    {requires_2fa} ─────►│
     │                                │                         │
     │                                │◄── auth_2fa {code} ────│
     │                                │──► auth_result          │
     │                                │    {success, jwt} ─────►│

Token Refresh for Long-Running Agents

Desktop agents and IoT bridges run 24/7. JWT tokens expire after 24h. CDAP supports token refresh:

// Client sends before token expires
{
  "type": "token_refresh",
  "payload": {
    "token": "current_jwt_about_to_expire"
  }
}

// Server responds with new token (no re-auth needed)
{
  "type": "token_refreshed",
  "payload": {
    "token": "new_jwt_24h",
    "expires_at": "2026-03-21T14:30:00Z"
  }
}

Rules:

  • Refresh only works if current token is still valid (not expired)
  • Max refresh chain: 30 days (then full re-auth required)
  • Admin can revoke refresh chain from panel (force re-login)
  • API key auth does not need refresh (keys don't expire by default)

RustDesk Client Synchronization

Problem Statement

A BetterDesk deployment typically has a mix of:

  • Existing RustDesk clients — already deployed on workstations, using RustDesk protocol on port 21116
  • New BetterDesk native clients (CDAP) — being rolled out, using CDAP on port 21122
  • IoT/SCADA bridges (CDAP) — new devices via CDAP

These must coexist in the same panel, same device list, same address books, same permissions.

Sync Points

1. Unified Peer Table

Both RustDesk and CDAP devices live in the same peers table:

-- Existing columns (unchanged)
id TEXT PRIMARY KEY,           -- "1340238749" (RustDesk) or "CDAP-D2E9F4" (CDAP)
uuid TEXT,
pk BLOB,
hostname TEXT,
os TEXT,
...

-- Existing CDAP columns (from Phase 1)
device_type TEXT DEFAULT 'rustdesk',  -- rustdesk, scada, iot, os_agent, desktop, ...
manifest_json TEXT,
bridge_id TEXT,
cdap_session_id TEXT,

-- NEW: Linking columns
linked_peer_id TEXT,           -- Cross-reference for dual-client machines
link_type TEXT,                -- "auto" (hostname match) or "manual" (admin linked)
auth_user TEXT,                -- Username who logged in on this device
last_auth_at TIMESTAMPTZ       -- Last CDAP/RustDesk login time

2. Address Book Convergence

RustDesk clients and CDAP clients share the same address book per user:

User "operator1" logs in from:
  ├── Node.js panel → sees all devices in panel
  ├── RustDesk client → GET /api/ab → sees address book
  └── CDAP native client → GET /api/ab (same endpoint) → sees address book

Address book contains:
  ├── RustDesk device IDs (numeric)
  └── CDAP device IDs (CDAP- prefix)

Both client types can:
  ├── Add devices to address book
  ├── Create tags/groups
  └── Sync across devices

The Go server's /api/ab endpoint already works for RustDesk clients. CDAP clients use the same endpoint with the same JWT token, so address books are automatically synchronized.

3. Connection History

When a CDAP client connects to another device (remote desktop):

// Audit log entry (same format as RustDesk connections)
{
  "action": "connection",
  "details": {
    "from_id": "CDAP-D2E9F4",
    "from_type": "desktop",
    "to_id": "892734561",
    "to_type": "rustdesk",
    "protocol": "cdap_media",
    "initiated_by": "operator1",
    "duration_sec": 1847,
    "timestamp": "2026-03-19T14:30:00Z"
  }
}

The Node.js panel's connection history view shows both RustDesk and CDAP connections in the same timeline.

4. Online Status Merging

The panel needs to query both connection pools:

Node.js Panel
     │
     ├── GET /api/peers (Go server)
     │    └── Go enriches with:
     │         ├── RustDesk live status (signal server in-memory map)
     │         └── CDAP live status (CDAP gateway in-memory map)
     │
     └── Shows unified device list with live status from both protocols

Implementation: handleListPeers in Go server already overlays live status from signal peer map. Extended to also check CDAP gateway's active connections map.

5. Linked Device View

When a machine runs both RustDesk and BetterDesk native clients:

Panel Device List:
┌──────────────────────────────────────────────────────────────┐
│  PC-Design-03                                    [Linked]    │
│  ├── 🖥️ 892734561   | RustDesk  | Online | Remote Desktop   │
│  └── 📱 CDAP-D2E9F4 | Desktop   | Online | Desktop + Mgmt   │
│                                                              │
│  srv-prod-01                                                 │
│  └── 💻 CDAP-F9A2B1 | OS Agent  | Online | System Management│
│                                                              │
│  Boiler Room PLC                                             │
│  └── 🏭 CDAP-A7F3B2 | SCADA     | Online | Widgets          │
└──────────────────────────────────────────────────────────────┘

Auto-linking algorithm:

  1. Same hostname + same user → auto-link
  2. Same IP (within 5 min window) + same hostname → suggest link
  3. Admin can manually link/unlink from panel

Implementation Phases

Phase 0: Preparation (1-2 days)

# Task Effort Files
0.1 Add device_type, manifest_json, linked_peer_id, auth_user columns to peers 0.5d db/sqlite.go, db/postgres.go
0.2 Add peer_links table for device linking 0.5d db/sqlite.go, db/postgres.go
0.3 Update handleListPeers to return device_type field 0.5d api/server.go
0.4 Add device type filter to panel device list 0.5d web-nodejs/views/, web-nodejs/routes/

Gate: Device list shows device_type column. All existing RustDesk devices show as rustdesk.


Phase 1: CDAP Gateway Core (5-7 days)

# Task Effort Files
1.1 Create cdap/ package with Gateway struct 1d cdap/gateway.go (NEW)
1.2 WebSocket server on port 21122 (gorilla/websocket) 1d cdap/gateway.go
1.3 Auth handler — user_password method (reuse auth.VerifyPassword) 0.5d cdap/auth.go (NEW)
1.4 Auth handler — api_key method (reuse auth.ValidateAPIKey) 0.5d cdap/auth.go
1.5 2FA handler — TOTP flow within WebSocket (reuse auth.ValidateTOTP) 0.5d cdap/auth.go
1.6 Rate limiting on auth messages (reuse ratelimit.IPLimiter) 0.5d cdap/auth.go
1.7 Manifest parser + validation (JSON Schema) 1d cdap/manifest.go (NEW)
1.8 Device registration — write to peers table with device_type 0.5d cdap/handler.go (NEW)
1.9 Heartbeat handler — widget value storage + online status 0.5d cdap/handler.go
1.10 Connection lifecycle — reconnect ID persistence by serial 0.5d cdap/handler.go
1.11 Wire into main.go — start CDAP gateway alongside signal/relay 0.5d main.go

Gate: Python bridge connects, authenticates (including 2FA), registers device, sends heartbeat. Device appears in peers table as device_type=scada.


Phase 2: Panel Widget Rendering (5-7 days)

# Task Effort Files
2.1 REST endpoint: GET /api/cdap/devices/{id}/manifest 0.5d api/server.go or cdap/api.go
2.2 REST endpoint: GET /api/cdap/devices/{id}/state (current widget values) 0.5d cdap/api.go
2.3 REST endpoint: POST /api/cdap/devices/{id}/command (send command) 0.5d cdap/api.go
2.4 WebSocket push: widget state changes → panel (via existing event bus) 1d cdap/handler.go, events/
2.5 Panel: CDAP device detail page (EJS template) 1d web-nodejs/views/cdap-device.ejs (NEW)
2.6 Panel: Widget renderer — toggle, gauge, button, led 2d web-nodejs/public/js/cdap-widgets.js (NEW)
2.7 Panel: Command sending UI (confirm dialogs, cooldowns) 1d web-nodejs/public/js/cdap-commands.js (NEW)
2.8 Panel: Device list shows device type icons + filter 0.5d web-nodejs/views/devices.ejs, devices.js
2.9 i18n keys for CDAP widgets and device types (EN + PL) 0.5d web-nodejs/lang/en.json, pl.json

Gate: Panel shows CDAP device detail with live-updating gauges, working toggle switches, functioning buttons with confirmations.


Phase 3: Security Hardening + Auth Convergence + Device Revocation (6-8 days)

# Task Effort Files
3.1 TLS auto-detection on CDAP port (reuse config.DualModeListener) 0.5d cdap/gateway.go
3.2 RBAC per-widget permissions enforcement 1d cdap/auth.go, cdap/handler.go
3.3 Command audit logging (every command → audit ring buffer) 0.5d cdap/handler.go, audit/
3.4 Device token enrollment (one-time tokens for new devices) 1d cdap/auth.go, db/
3.5 Token refresh for long-running agents (30-day chain) 0.5d cdap/auth.go
3.6 Auth delegation: Node.js panel uses Go /api/auth/ for user CRUD 1d web-nodejs/services/authService.js (NEW)
3.7 Panel: user management through Go API (password change syncs to Go) 0.5d web-nodejs/routes/auth.routes.js
3.8 Device Revocation: CDAP revoke + suspend message handlers in gateway 1d cdap/revocation.go (NEW), cdap/gateway.go
3.9 Connection close on delete: Close TCPConn/WSConn when peer removed from map 0.5d peer/map.go, api/server.go
3.10 Blocklist on revoke: Auto-add ID to security.Blocklist on ?revoke=true 0.5d api/server.go, security/blocklist.go
3.11 Cascade delete: Revoke linked_peer_id when cascade option selected 0.5d cdap/revocation.go, api/server.go
3.12 Panel revocation UI: Delete dialog with wipe/blocklist/cascade checkboxes 1d web-nodejs/views/, public/js/devices.js
3.13 EventPeerRevoked: New event type on event bus for revocation audit trail 0.25d events/bus.go

Gate: Widget RBAC enforced (operator can read gauge but not trigger emergency stop without permission). 2FA works end-to-end for CDAP clients. Password changed in panel reflects in CDAP login. Deleting a CDAP device sends revoke message → client wipes config and disconnects. Cascade delete revokes linked devices.


Phase 4: Advanced Widgets + RustDesk Sync (5-7 days)

# Task Effort Files
4.1 Widget types: chart, select, slider, text 2d web-nodejs/public/js/cdap-widgets.js
4.2 Widget types: table (dynamic rows, sortable) 1d cdap-widgets.js
4.3 Widget type: terminal (WebSocket shell relay) 2d cdap/terminal.go (NEW), cdap-widgets.js
4.4 Device linking — auto-detect + manual link in panel 1d cdap/linking.go (NEW), panel views
4.5 Unified status overlay — CDAP status merged into handleListPeers 0.5d api/server.go
4.6 Address book sync — CDAP clients use same /api/ab endpoint 0.5d cdap/api.go (proxy or direct)
4.7 Connection history — CDAP events in same audit format 0.5d cdap/handler.go, web-nodejs/routes/

Gate: Full 10+ widget types working. Linked devices show as one machine in panel. Address book shared between RustDesk and CDAP clients.


Phase 5: Media Channel — Remote Desktop (10-15 days)

# Task Effort Files
5.1 Binary frame mux/demux in CDAP gateway 2d cdap/media.go (NEW)
5.2 Media session establishment (REST /api/cdap/devices/{id}/connect) 1d cdap/api.go
5.3 Binary frame relay (viewer ↔ device, E2E opaque) 1d cdap/media.go
5.4 E2E key exchange (X25519 → XSalsa20-Poly1305 via control messages) 1d cdap/crypto.go (NEW)
5.5 Video channel: codec negotiation + keyframe request handling 1d cdap/media.go
5.6 Panel: WebCodecs/Canvas desktop viewer widget 3d web-nodejs/public/js/cdap-desktop.js (NEW)
5.7 Panel: input forwarding (keyboard/mouse → binary frames) 1d cdap-desktop.js
5.8 Panel: clipboard sync widget 1d cdap-desktop.js
5.9 Panel: file transfer two-pane browser 2d web-nodejs/public/js/cdap-files.js (NEW)
5.10 Audio channel: Opus decode/play in browser 1d cdap-desktop.js
5.11 Cursor channel: custom cursor rendering 0.5d cdap-desktop.js
5.12 Adaptive quality (bitrate/fps adjustments) 1d cdap/media.go
5.13 Multi-monitor support (display index routing) 0.5d cdap/media.go, cdap-desktop.js

Gate: Panel can open remote desktop session to a CDAP desktop device. Video, audio, input, clipboard, and file transfer all work through the binary media channel with E2E encryption.


Phase 6: Native BetterDesk Desktop Agent (10-15 days)

# Task Effort Files
6.1 Agent binary scaffold (Rust or Go) — systemd/service installer 2d betterdesk-agent/ (NEW repo or dir)
6.2 CDAP client library — auth + heartbeat + manifest 2d betterdesk-agent/cdap/
6.3 Screen capture — DXGI (Windows), X11/PipeWire (Linux) 2d betterdesk-agent/capture/
6.4 Video encoder — H.264/VP9 hardware-accelerated 2d betterdesk-agent/encoder/
6.5 Audio capture — WASAPI (Windows), PulseAudio (Linux) 1d betterdesk-agent/audio/
6.6 Input injection — keyboard/mouse (platform-specific) 1d betterdesk-agent/input/
6.7 Clipboard monitor — text/image sync 1d betterdesk-agent/clipboard/
6.8 File transfer — chunk read/write with resume 1d betterdesk-agent/files/
6.9 System widgets — CPU/RAM/disk/services/processes 1d betterdesk-agent/sysinfo/
6.10 Login UI — username/password + 2FA dialog 1d betterdesk-agent/ui/
6.11 Tray icon + auto-start 0.5d betterdesk-agent/ui/
6.12 Update from ALL-IN-ONE scripts (install/update support) 1d betterdesk.sh, betterdesk.ps1

Gate: BetterDesk agent installs on Windows/Linux, logs in with 2FA, appears as desktop type in panel, supports remote desktop + system management widgets.


Phase 7: Bridge Ecosystem + Polish (5-7 days)

# Task Effort Files
7.1 Python bridge SDK (pip-installable) 1d sdks/python/ (NEW)
7.2 Reference bridge: Modbus TCP 1d bridges/modbus/ (NEW)
7.3 Reference bridge: SNMP 1d bridges/snmp/ (NEW)
7.4 Reference bridge: REST/HTTP (generic webhook → CDAP) 1d bridges/rest/ (NEW)
7.5 Dashboard: CDAP device type counters + overview cards 1d Panel views
7.6 Alert system: threshold-based from manifest definitions 1d cdap/alerts.go (NEW)
7.7 Documentation site / updated README 1d docs/

Gate: Three working reference bridges. Alert system notifies on threshold breach. Dashboard shows CDAP devices alongside RustDesk.


File-Level Change Map

Go Server (betterdesk-server/)

File Action Phase Description
main.go Modify 1 Start CDAP gateway, pass config
config/config.go Modify 1 Add CDAPPort, CDAPTLSEnabled()
cdap/gateway.go NEW 1 WebSocket server, connection lifecycle
cdap/auth.go NEW 1 Auth handler (user/pass, API key, 2FA, device token)
cdap/handler.go NEW 1 Register, heartbeat, state_update, command routing
cdap/manifest.go NEW 1 Manifest parsing + JSON validation
cdap/api.go NEW 2 REST endpoints for panel (manifest, state, command)
cdap/terminal.go NEW 4 Terminal widget WebSocket relay
cdap/linking.go NEW 4 Device auto-linking logic
cdap/media.go NEW 5 Binary frame mux/demux, media session, relay
cdap/crypto.go NEW 5 X25519 key exchange for E2E media
cdap/revocation.go NEW 3 Revoke/suspend message sending, cascade logic, conn close
cdap/alerts.go NEW 7 Threshold-based alert evaluation
db/database.go Modify 0-1 Add CDAP-related methods to interface
db/sqlite.go Modify 0-1 Implement CDAP methods, add columns/tables
db/postgres.go Modify 0-1 Same for PostgreSQL
peer/map.go Modify 3 Close TCP/WS connections on Remove()
api/server.go Modify 2-4 CDAP REST routes, status overlay, ?revoke=true in delete
events/bus.go Modify 3 Add EventPeerRevoked event type
security/blocklist.go Modify 3 Auto-add ID on revocation
auth/ (existing) No change Reused by CDAP auth (no modification needed)

Node.js Console (web-nodejs/)

File Action Phase Description
views/cdap-device.ejs NEW 2 CDAP device detail page with widget panel
views/devices.ejs Modify 0 Add device type column, filter, icons
public/js/cdap-widgets.js NEW 2 Widget renderer (all 13 types)
public/js/cdap-commands.js NEW 2 Command sending, confirmation, cooldown
public/js/cdap-desktop.js NEW 5 Remote desktop viewer (WebCodecs + Canvas)
public/js/cdap-files.js NEW 5 Two-pane file browser
public/css/cdap.css NEW 2 Widget styles, device type icons
routes/cdap.routes.js NEW 2 CDAP panel routes (proxy to Go server)
services/authService.js NEW 3 Auth delegation to Go server
lang/en.json Modify 2+ CDAP i18n keys
lang/pl.json Modify 2+ CDAP i18n keys
services/betterdeskApi.js Modify 2 Add CDAP API methods

ALL-IN-ONE Scripts

File Action Phase Description
betterdesk.sh Modify 6 CDAP port in firewall, agent install option
betterdesk.ps1 Modify 6 Same for Windows
betterdesk-docker.sh Modify 1 Expose port 21122 in docker-compose
docker-compose.yml Modify 1 Add port 21122 mapping
Dockerfile Modify 1 Expose 21122

Testing Strategy

Unit Tests (Go)

Test Phase Validates
cdap/auth_test.go 1 Auth message parsing, password verify, API key, 2FA flow
cdap/manifest_test.go 1 Manifest validation (valid, invalid, edge cases)
cdap/handler_test.go 1 Register, heartbeat, state_update, command routing
cdap/media_test.go 5 Binary frame mux/demux, session pairing
cdap/linking_test.go 4 Auto-link algorithm, unlink
cdap/revocation_test.go 3 Revoke message sent, conn closed, config wipe, cascade

Integration Tests

Test Phase Setup Validates
Bridge auth flow 1 Go server + Python bridge WS connect → auth → register → heartbeat
2FA end-to-end 1 Go server + test TOTP Auth → 2FA required → code verify → session
Panel widget rendering 2 Full stack Bridge connects → panel shows widgets → values update
Command round-trip 2 Full stack Panel sends command → bridge receives → executes → response
Linked devices 4 Go server + RustDesk + CDAP Both clients online → panel shows linked view
Device revocation 3 Go server + CDAP bridge Delete → revoke msg → bridge disconnects + wipes config
Cascade revocation 3 Go server + RustDesk + CDAP Delete CDAP → linked RustDesk also revoked + blocked
Media relay 5 Go server + 2 CDAP clients Video frames relayed with E2E encryption

Load Tests

Test Phase Target
100 concurrent CDAP devices 2 Gateway handles 100 WS connections, 1000 msg/s
10 concurrent media sessions 5 Binary relay at 10 Mbps aggregate without frame loss
1000 widget updates/sec 2 Panel receives updates via WS push without lag

Migration & Backward Compatibility

Zero Breaking Changes

  • All existing RustDesk clients continue working unchanged
  • All existing Node.js panel features unchanged
  • All existing API endpoints unchanged
  • CDAP is strictly additive — new port, new protocol, new device types

Migration Path for Organizations

Step 1: Update BetterDesk server (Phase 1-4)
  └── CDAP gateway starts on port 21122
  └── All existing devices still work

Step 2: Deploy IoT/SCADA bridges (Phase 2+)
  └── New device types appear in panel
  └── RustDesk devices unaffected

Step 3: Deploy BetterDesk native agent on select machines (Phase 6)
  └── Machine shows two entries (RustDesk + CDAP)
  └── Admin can link them in panel

Step 4: Gradually replace RustDesk client with native agent
  └── Uninstall RustDesk client
  └── CDAP agent provides remote desktop + management
  └── One device entry per machine

Step 5 (optional): Disable RustDesk protocol
  └── Only for environments fully migrated to CDAP
  └── Signal/relay servers still available for backward compat

Rollback

Every phase is independent. If Phase 5 (media) has issues, Phases 1-4 (widgets, auth, sync) continue working. CDAP gateway can be disabled entirely by removing the --cdap-port flag — zero impact on RustDesk protocol.


Risk Assessment

Risk Impact Likelihood Mitigation
WebSocket scalability at 1000+ devices High Medium Connection pooling, per-device message throttle
Auth DB divergence (Node.js vs Go) High High Phase 3 convergence, sync checks
Binary frame relay performance for desktop High Low E2E opaque (zero decode), tested architecture
Native agent cross-platform complexity High High Start with one platform (Linux or Windows), add second
Bridge SDK maintenance burden Medium Medium Minimal SDKs (~200 LOC), auto-generate from spec
RustDesk protocol changes break existing Medium Low BetterDesk server frozen at RustDesk 1.3.x compat
2FA lockout (lost phone, no recovery codes) Medium Medium Admin can disable 2FA from panel, recovery codes backup reminder
CDAP spec changes during development Medium Medium Versioned manifests, backward compat
Revocation message not delivered (device offline) Medium High Blocklist + soft-delete ensure re-registration fails regardless; revoke is best-effort optimization
Cascade delete accidental scope High Low Cascade is opt-in checkbox, admin must explicitly confirm; audited
RustDesk client cannot be config-wiped Medium N/A Protocol limitation; blocklist prevents re-registration; BetterDesk native client supports full wipe

Timeline Summary

Phase Duration Cumulative Key Deliverable
0: Preparation 1-2 days 1-2 days DB schema, device type column
1: Gateway Core 5-7 days 6-9 days CDAP auth + registration working
2: Panel Widgets 5-7 days 11-16 days Widgets visible and interactive in panel
3: Security + Auth + Revocation 6-8 days 17-25 days Full RBAC + 2FA + auth convergence + device revocation
4: Advanced + Sync 5-7 days 22-32 days Full widget set + RustDesk sync
5: Media Channel 10-15 days 32-47 days Remote desktop via CDAP
6: Native Agent 10-15 days 42-62 days BetterDesk desktop agent binary
7: Ecosystem 5-7 days 47-69 days Bridge SDKs + reference bridges

MVP (Phases 0-2): ~16 days → CDAP devices with widgets in panel
Production (Phases 0-4): ~32 days → Secure, synced, full widget set + revocation
Full Stack (Phases 0-7): ~69 days → Native client + bridge ecosystem