Adds an admin UI page that produces an Ed25519-signed custom.txt the
patched RustDesk client picks up at startup. The blob carries
app-name, default-settings, override-settings, an optional logo
image, and arbitrary buildin keys.
- gen_branding_sk + read_branding_sk + read_branding_pubkey in
common.rs; called once on hbbs startup so the branding keypair
(separate from the rendezvous id_ed25519) is created on first boot
alongside it. Decoupling lets the two rotate independently.
- src/api/admin/pages/customization.rs: form with multipart logo
upload (PNG/ICO/JPEG, magic-byte sniffed, capped at 256 KiB), JSON
default/override settings fields, kv-pair rows for arbitrary
buildin keys. Signs with sodiumoxide and emits standard-base64
matching the client's decode64 path. Result block has a copyable
blob and a "Download custom.txt" button.
- Routes wired under /admin/pages/customization{,/generate,/download}
and the admin nav gets a Customization link.
- src/verify_branding.rs: smoke-test binary the operator can run
before cutting a client release to confirm the signature
round-trips.
- axum gains the multipart feature flag for the upload handler.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>