enroll(rustdesk-server): test suite + bridge poll #48

Merged
autonomic-bot merged 3 commits from test/rustdesk-server-enroll-20261030 into main 2026-10-30 21:15:59 +00:00
Owner

Enroll rustdesk-server as a maintained recipe: test suite + !testme bridge poll + weekly inventory.

What's enrolled

tests/rustdesk-server/ — the recipe is NOT HTTP-native (hbbs/hbbr speak a protobuf protocol on host-published 21115-21119, 21116 also UDP; 21118/21119 websocket), so the suite follows the mumble pattern with one twist:

  • compose.ccci.yml (environmental overlay, all deploys) — a status sidecar (nginx) serves exactly ONE real app artifact at /id_ed25519.pub: hbbs's generated identity public key, read-only from the shared rustdesk_data volume. The HTTP health gate therefore asserts the domain routes AND hbbs actually minted its keypair — never a canned page. The private key + sqlite peer DB in the same volume are asserted unreachable (exact-location config, everything else 404s; workers run as root because the volume dir is 0700, noted inline).
  • recipe_meta.py — HEALTH_PATH=/id_ed25519.pub, READY_PROBE = stable TCP on 127.0.0.1:21116 (stock compose publishes the ports mode:host), WARM_CANONICAL=True, BACKUP_CAPABLE unset (no backupbot labels upstream → tiers intentionally auto-skip).

The tests (custom tier, ≥2 required, 4 shipped)

file verifies non-vacuous because
test_rendezvous_ports.py all 5 stock ports listening, 21116 stable 3x per-port naming of any bind failure
test_websocket_handshake.py real 101 Switching Protocols on :21118/:21119 bare GET gets NO response — 101 can only come from a serving hbbs/hbbr
test_identity_key.py identity key EQUAL across 3 surfaces (HTTPS status route / hbbs Key: log line / volume file), valid 32-byte ed25519; private key + DB paths 404 the §4.3-style round-trip of the recipe's defining generated state; mismatch names the broken layer
test_punch_hole_no_amplification.py unauthenticated UDP punch-hole request → SILENCE on ≥1.1.16, while register_peer on the same socket IS answered security regression test for the 1.1.16 amplification fix (GH rustdesk/rustdesk-server#670, actively exploited pre-fix even with -k _; CVE-2026-30784 was reserved then withdrawn). In-test register_peer response proves silence means "fixed", not "broken". Version-gated per STYLE §2

Empirical baseline (recorded in the test file, dev deploys of base + head on the cc-ci swarm, 2026-10-30):

  • 1.1.12: register_peer → 3a021001 (register_peer_response); unauthenticated punch_hole_request ×3 → 5a021803 (punch_hole_response) EVERY time — the amplification, live-confirmed
  • 1.1.16: register_peer → unchanged; punch_hole_request ×3 → silence

The protobuf probes are hand-encoded from the upstream rendezvous.proto (field numbers verified identical between the 1.1.12-vendored and current shared-proto tags) — stdlib only, the mumble _mumble_proto pattern.

Also in this PR

  • nix/modules/bridge.nix: POLL_REPOS += recipe-maintainers/rustdesk-server (the !testme trigger).
  • Weekly inventory row (orchestrator repo, doc commit).

Context

Operator-requested one-off upgrade (recipe PR recipe-maintainers/rustdesk-server#1, 1.1.12→1.1.16, unmerged) turned into a full enrollment at the operator's call: single client, low-churn upstream (4 releases in 2 years, zero breaking changes) = cheap to keep current. The upgrade PR will get its !testme card once the bridge polls the new repo.

Verify plan

Cold full-suite green vs recipe main (overlay + base 1.1.12 deploy) via the standard verify-pr path on the cc-ci host, then bridge deploy (test-before-switch), then !testme on the recipe PR. Evidence will be commented on this PR before merge.

Enroll `rustdesk-server` as a maintained recipe: test suite + `!testme` bridge poll + weekly inventory. ## What's enrolled `tests/rustdesk-server/` — the recipe is NOT HTTP-native (hbbs/hbbr speak a protobuf protocol on host-published 21115-21119, 21116 also UDP; 21118/21119 websocket), so the suite follows the mumble pattern with one twist: - **`compose.ccci.yml` (environmental overlay, all deploys)** — a `status` sidecar (nginx) serves exactly ONE real app artifact at `/id_ed25519.pub`: hbbs's generated identity public key, read-only from the shared `rustdesk_data` volume. The HTTP health gate therefore asserts the domain routes AND hbbs actually minted its keypair — never a canned page. The private key + sqlite peer DB in the same volume are asserted unreachable (exact-location config, everything else 404s; workers run as root because the volume dir is 0700, noted inline). - **`recipe_meta.py`** — `HEALTH_PATH=/id_ed25519.pub`, `READY_PROBE` = stable TCP on 127.0.0.1:21116 (stock compose publishes the ports mode:host), `WARM_CANONICAL=True`, `BACKUP_CAPABLE` unset (no backupbot labels upstream → tiers intentionally auto-skip). ## The tests (custom tier, ≥2 required, 4 shipped) | file | verifies | non-vacuous because | |---|---|---| | `test_rendezvous_ports.py` | all 5 stock ports listening, 21116 stable 3x | per-port naming of any bind failure | | `test_websocket_handshake.py` | real `101 Switching Protocols` on :21118/:21119 | bare GET gets NO response — 101 can only come from a serving hbbs/hbbr | | `test_identity_key.py` | identity key EQUAL across 3 surfaces (HTTPS status route / hbbs `Key:` log line / volume file), valid 32-byte ed25519; private key + DB paths 404 | the §4.3-style round-trip of the recipe's defining generated state; mismatch names the broken layer | | `test_punch_hole_no_amplification.py` | unauthenticated UDP punch-hole request → SILENCE on ≥1.1.16, while register_peer on the same socket IS answered | **security regression test for the 1.1.16 amplification fix** (GH rustdesk/rustdesk-server#670, actively exploited pre-fix even with `-k _`; CVE-2026-30784 was reserved then withdrawn). In-test register_peer response proves silence means "fixed", not "broken". Version-gated per STYLE §2 | **Empirical baseline (recorded in the test file, dev deploys of base + head on the cc-ci swarm, 2026-10-30):** - 1.1.12: `register_peer` → `3a021001` (register_peer_response); unauthenticated `punch_hole_request` ×3 → `5a021803` (punch_hole_response) EVERY time — the amplification, live-confirmed - 1.1.16: `register_peer` → unchanged; `punch_hole_request` ×3 → silence The protobuf probes are hand-encoded from the upstream `rendezvous.proto` (field numbers verified identical between the 1.1.12-vendored and current shared-proto tags) — stdlib only, the mumble `_mumble_proto` pattern. ## Also in this PR - `nix/modules/bridge.nix`: `POLL_REPOS` += `recipe-maintainers/rustdesk-server` (the `!testme` trigger). - Weekly inventory row (orchestrator repo, doc commit). ## Context Operator-requested one-off upgrade (recipe PR https://git.autonomic.zone/recipe-maintainers/rustdesk-server/pulls/1, 1.1.12→1.1.16, unmerged) turned into a full enrollment at the operator's call: single client, low-churn upstream (4 releases in 2 years, zero breaking changes) = cheap to keep current. The upgrade PR will get its `!testme` card once the bridge polls the new repo. ## Verify plan Cold full-suite green vs recipe `main` (overlay + base 1.1.12 deploy) via the standard verify-pr path on the cc-ci host, then bridge deploy (test-before-switch), then `!testme` on the recipe PR. Evidence will be commented on this PR before merge.
autonomic-bot added 1 commit 2026-10-30 18:58:59 +00:00
autonomic-bot requested review from trav 2026-10-30 18:58:59 +00:00
autonomic-bot requested review from notplants 2026-10-30 18:58:59 +00:00
autonomic-bot added 1 commit 2026-10-30 19:03:02 +00:00
autonomic-bot added 1 commit 2026-10-30 19:03:15 +00:00
chore(rustdesk): drop unused import
continuous-integration/drone/push Build is passing
f5f11cd769
Author
Owner

Enrollment verification (skill gate = cold full-suite green) — done, two runs:

Run 1 — RED → fixed the gate (never weakened the assertion). REF=main (e2f87735, recipe 1.0.4+1.1.12), log cc-ci:/root/cc-ci-review-logs/verify-rustdesk-server-20261030T185926Z.1.log: install pass, upgrade pass, custom = identity-key 5/5 pass, ports 2/2 pass, websocket 1/1 pass, punch-hole_amplification FAILED. Cause: my hand-rolled docker service inspect version read returned None, so the <1.1.16 skip gate never fired and the test observed the expected pre-fix behavior on a 1.1.12 head (hbbs answering unauthenticated punch-hole: 5a021803 ×3). Fix (1653582 + f5f11cd): read the version via the harness's own lifecycle.deployed_identity(), strip any @sha256: digest, and pytest.fail loudly when the tag is unparsable — a gate that cannot decide must never silently run or silently skip.

Run 2 — GREEN, level 5/5. REF=main, log verify-rustdesk-server-20261030T190318Z.1.log: install/upgrade/custom all pass, punch-hole test SKIPPED on 1.1.12 (pre-fix = expected, covered by upgrade-tier base deploy).

Run 3 — GREEN, level 5/5, against the actual upgrade head. REF=upgrade-2e65135 (recipe PR recipe-maintainers/rustdesk-server#1, 1.1.16), log verify-rustdesk-server-20261030T190513Z.1.log: punch-hole test PASSED ACTIVE — unauthenticated punch-hole is silent on 1.1.16 ×3 while register_peer still answers (field 7 sanity), i.e. the amplification regression guard verified in the real harness.

Both cards rendered (/var/lib/cc-ci-runs/manual/summary.png), deploy-count 1 run each, swarm torn down clean. Next: host rebuild (test→switch) to activate the POLL_REPOS change, then !testme on the recipe PR.

Enrollment verification (skill gate = cold full-suite green) — done, two runs: **Run 1 — RED → fixed the gate (never weakened the assertion).** `REF=main` (`e2f87735`, recipe 1.0.4+1.1.12), log `cc-ci:/root/cc-ci-review-logs/verify-rustdesk-server-20261030T185926Z.1.log`: install pass, upgrade pass, custom = identity-key **5/5 pass**, ports **2/2 pass**, websocket **1/1 pass**, punch-hole_amplification FAILED. Cause: my hand-rolled `docker service inspect` version read returned None, so the `<1.1.16` skip gate never fired and the test observed the *expected pre-fix* behavior on a 1.1.12 head (hbbs answering unauthenticated punch-hole: `5a021803` ×3). Fix (1653582 + f5f11cd): read the version via the harness's own `lifecycle.deployed_identity()`, strip any `@sha256:` digest, and **pytest.fail loudly** when the tag is unparsable — a gate that cannot decide must never silently run or silently skip. **Run 2 — GREEN, level 5/5.** `REF=main`, log `verify-rustdesk-server-20261030T190318Z.1.log`: install/upgrade/custom all pass, punch-hole test SKIPPED on 1.1.12 (pre-fix = expected, covered by upgrade-tier base deploy). **Run 3 — GREEN, level 5/5, against the actual upgrade head.** `REF=upgrade-2e65135` (recipe PR https://git.autonomic.zone/recipe-maintainers/rustdesk-server/pulls/1, 1.1.16), log `verify-rustdesk-server-20261030T190513Z.1.log`: punch-hole test **PASSED ACTIVE** — unauthenticated punch-hole is silent on 1.1.16 ×3 while register_peer still answers (field 7 sanity), i.e. the amplification regression guard verified in the real harness. Both cards rendered (`/var/lib/cc-ci-runs/manual/summary.png`), deploy-count 1 run each, swarm torn down clean. Next: host rebuild (test→switch) to activate the `POLL_REPOS` change, then `!testme` on the recipe PR.
autonomic-bot merged commit a8b836ed1d into main 2026-10-30 21:15:59 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: recipe-maintainers/cc-ci#48