- Protocol::Rdp with RdpConfig (domain, password mode, certificate
policy, TLS-only fallback, fixed or tab-sized resolution, SOCKS5/HTTP
proxy, SSH tunnel); migration 008 adds rdp_config and drops the
protocol CHECK constraint so new protocols no longer need a rebuild.
- Session manager: connect_rdp dials directly, via the shared proxy
module (proxy password from the secret store) or an SSH tunnel; the
server certificate goes through the known-hosts check (key type
rdp-tls); a tab-sized desktop uses the tab's reported pixel size, and
resizes wait until the server opens Display Control. Rejected NLA
passwords count as auth failures, so a saved one is asked again.
- The VNC viewer becomes DesktopView for both protocols; a small adapter
turns its keysyms and pointer masks into RDP scancodes, Unicode keys,
buttons and wheel events. For RDP, Paste Clipboard types the text.
- Profile editor RDP section, Quick Connect, badges, docs.
Verified against xrdp in the app: logon, desktop, input, and connections
through SOCKS5 and HTTP CONNECT relays. Not verified here: Windows/NLA
servers, the SSH tunnel route, and Display Control resizing (xrdp
0.9.24 never opened the channel).
Keychain reads no longer fall back to the AlchementaryLink service and
copy entries forward, and Windows Credential Manager entries use
keyring's own target naming instead of go-keyring's 'service:user'.
Credentials saved by Alchementary Link, or by earlier builds on Windows,
are no longer found and need re-entering.
SshConfig no longer has proxyPassword or totpSecret fields, so neither
can sit in clear in nexus.db or travel in an export. The proxy password
is a SecretKind (profile:<id>:proxy-password) edited like other saved
credentials and purged with the profile; the session manager hands both
it and the TOTP seed to the SSH client from the keychain/vault at
connect time.
This drops compatibility with Go-era profiles and .link/.nexus files
that carry these values inline: they are ignored on read and must be
re-entered (SEC-20261012-011).
Session-only credentials (kept for a whole session so reconnects don't
re-prompt), credentials pending until a connection succeeds, and the
credential prompt's text buffer are now Zeroizing and wiped when
dropped, including when a prompt is cancelled or abandoned
(SEC-20261012-007, partial).
Still open: the values handed to the protocol clients are plain Strings
for the duration of authentication, egui keeps its own copies of typed
text, and no mlock/PR_SET_DUMPABLE is applied.
- A JSON export without secrets now blanks login-script 'send' steps that
answer a password-like 'wait' prompt (SSH and Telnet), not just the
proxy password and inline TOTP seed (SEC-20261012-011, partial).
- Credential kinds were string literals in the session manager, profile
editor and secret store; they are now SecretKind with one ALL list, so
the profile-delete purge can't miss a kind (F19).
Moving proxyPassword out of the profile record is left open: it changes
.link/.nexus compatibility with the Go app and needs an owner decision.
Every shared lock was std::sync::Mutex with lock().unwrap() (~150 sites),
so a panic in any session's reader or callback poisoned the lock and the
next UI frame panicked too, dropping every open session. Locks are now
parking_lot::Mutex (no poisoning; already in the dependency tree), and a
panic hook reports worker panics as an error toast instead of the session
silently stopping (F3, F4).
A password typed at a 'saved' prompt was stored before the server
accepted it, so a typo was persisted and silently retried on every
reconnect. Typed values are now held per attempt and written once the
session connects; when the server refuses a saved credential the next
attempt asks again and the new value replaces it on success. A store
failure (keychain refused, vault locked) now shows a toast instead of
being swallowed, and reconnect prompts wait 5 minutes like the first
connect (SEC-20261012-015, F1, F2, F20).
Under the 'ask' policy a changed host key used to be a hard error. The
prompt now shows the stored and received fingerprints and offers Reject,
Accept Once (connect, keep the record) and Accept & Update (replace the
record; audited). Unknown keys gain an Accept Once option too. Strict and
accept-new still refuse changed keys without prompting. Known-host rows
written by the old app are confirmed removable by id (test).
The NickServ password (and any other "remember for this session" secret) was
resolved through a fresh per-connect cache, so every auto-reconnect prompted
again with a 60 s timeout and an unanswered prompt failed the reconnect.
Session-only secrets now live on the session, survive auto and explicit
reconnects, and IDENTIFY is sent on every registration as before.