Files
cc-ci/tests/rustdesk-server/PARITY.md
T

45 lines
3.8 KiB
Markdown

# Parity — rustdesk-server
The recipe-maintainer corpus has **no** `recipe-info/rustdesk-server/` directory — rustdesk-server
was never in the recipe-maintainer parity suite (this is a fresh 2026-10-30 enrollment, requested
as a one-off upgrade of a single-client production deploy). So this PARITY.md documents the
cc-ci-authored suite as the baseline.
## The recipe's shape (why the suite looks like this)
rustdesk-server is **not HTTP-native**: hbbs (rendezvous/registry) + hbbr (relay) speak a
hand-rolled protobuf protocol on host-published ports 21115-21119 (21116 also UDP; 21118/21119
websocket). There is no web UI, no HTTP API, and the stock compose's traefik labels point at a
port nothing serves. The cc-ci ENVIRONMENTAL overlay (`compose.ccci.yml`) adds a `status`
sidecar serving exactly hbbs's generated identity PUBLIC key at `/id_ed25519.pub` — the HTTP
health gate then asserts real app state (the key only exists because hbbs minted it), never a
canned page. The private key + sqlite peer DB in the same volume are asserted UNREACHABLE.
Host ports need no overlay: the stock compose publishes them mode:host, so protocol tests run
on-host at 127.0.0.1 (the mumble pattern).
## Recipe-specific tests (≥2 beyond the generic floor)
| cc-ci file | what's verified | why non-vacuous |
|---|---|---|
| `custom/test_rendezvous_ports.py` | All 5 stock host-published ports (21115-21119) accept TCP; 21116 holds 3 consecutive connects. | The recipe's entire function is serving those ports; a missing/failed bind (e.g. a compose port change upstream) is named per-port. |
| `custom/test_websocket_handshake.py` | Real `101 Switching Protocols` upgrades on hbbs :21118 and hbbr :21119. | These are the app's own client-facing protocol listeners; a bare GET gets NO response, so 101 can only come from a genuinely serving hbbs/hbbr (verified live on 1.1.12 and 1.1.16). |
| `custom/test_identity_key.py` | hbbs's ed25519 identity key read back through THREE independent surfaces — HTTPS status route (via Traefik), hbbs's own `Key:` startup log, the volume file — asserted EQUAL and a valid 32-byte key; plus the private key / DB paths asserted 404. | The §4.3-style round-trip of the recipe's defining generated state; a crash-looping hbbs (no key) fails, a routing gap fails, a surface mismatch (reading another deployment) fails, and an exposure fails. |
| `custom/test_punch_hole_no_amplification.py` | An unauthenticated UDP punch-hole request gets NO response on ≥1.1.16, while a register_peer sanity probe on the same socket IS answered. | The security regression test for the 1.1.16 amplification fix (GH #670, actively exploited pre-fix even with `-k _`). The in-test register_peer response proves silence means "fixed", not "broken"; a regression turns this RED naming the layer. Empirical baseline recorded in the file (1.1.12 answered 3/3, 1.1.16 silent 3/3). Version-gated per STYLE §2. |
## Backup data-integrity
The stock recipe declares no `backupbot.backup` labels — backup/restore tiers auto-skip
(intentional non-run, auto-detected). Nothing here weakens that; if the recipe grows backup
support upstream, the generic tiers pick it up automatically.
## Deferred
- A full register_pk/punch-hole EXCHANGE between two registered peers (proving the happy-path
connection flow, not just the refusal) — needs the client-side crypto handshake (signed pk
registration); the register_peer + ws + punch-hole surfaces already cover the server's
externally observable behavior. Revisit if upstream changes the rendezvous flow.
- Host-port contention: 21115-21119 are unique to this recipe, but two CONCURRENT rustdesk
deploys (e.g. a cold run racing a canonical reattach) would collide on them — same exposure
mailu (25/465/587) and lasuite-meet (7882) already carry as host-port recipes. Cadence makes
a collision rare; a failed deploy is loud and re-runnable.