Files
orbithub/docs/PROGRESS.md
T
ksmithandClaude Sonnet 5 6da9dc6ca5 Add VNC support (Milestone 6, issue #3)
Implements RFB (RFC 6143) directly against QTcpSocket. No permissively
licensed VNC client library exists to vendor the way FreeRDP was for RDP:
LibVNCClient is GPLv2, gtk-vnc is LGPL but GTK-tied, and vendoring either
would force a licensing decision on the whole (MIT) project. This is
from-scratch protocol code instead, threaded like SshSessionBackend (a
QObject on its own QThread driven by Qt's own async socket signals)
rather than RdpSessionBackend's manual worker-thread/blocking-loop
pattern, since QTcpSocket is already async.

Scope, matching SessionTab's existing SSH/RDP dispatch pattern
(session_backend_factory.cpp, session_tab.cpp's widget construction and
signal wiring) and VncDisplayWidget mirroring RdpDisplayWidget's
scale-to-fit rendering:
- Protocol handshake: RFB 3.3/3.7/3.8 negotiated explicitly (the
  SecurityResult message only exists in 3.8; pre-3.8 servers signal auth
  failure by closing the socket, which the disconnect handler accounts
  for)
- VNC Authentication (DES challenge-response, via OpenSSL's classic DES
  API) and no-auth security types
- Raw + CopyRect framebuffer decoding into a persistent QImage, requesting
  a fixed 32bpp format whose byte layout matches QImage::Format_RGB32
  directly (same zero-conversion trick RdpSessionBackend uses for
  FreeRDP's GDI buffer)
- Keyboard (Qt key -> X11 keysym, including the Unicode-beyond-Latin-1
  keysym convention) and mouse/wheel input forwarding

Explicit non-goals for this pass (see docs/PROGRESS.md for the full
list): Apple's Screen Sharing auth (so this can't yet reach macOS's
built-in VNC server), compression encodings beyond Raw/CopyRect, dynamic
resize, remote cursor shape sync, clipboard sync.

19 unit tests (tests/test_vnc_session_backend.cpp): pure-function
coverage (DES key prep verified against an independently documented test
vector for password "COW", X11 keysym mapping, socket-error mapping) plus
state-machine coverage against a scripted in-process fake RFB server
covering all three protocol-version handshake shapes, auth success/
failure, unsupported security types, and pixel-accurate Raw decoding.
That harness caught a real re-entrancy bug: QAbstractSocket::abort()
synchronously re-emits disconnected() before returning, so
failConnection() calling it was silently letting a second, generic
disconnected-socket handler overwrite an already-correct, specific error
message.

Also verified live against a real, independently implemented VNC server
(TightVNC on Windows): connect with VNC Authentication, correct
framebuffer dimensions and pixel data, clean disconnect, reconnect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-15 18:02:49 -06:00

14 KiB

OrbitHub Progress

Milestone 0 - Restart in C++/Qt Widgets

Status: Completed

Delivered:

  • Fresh C++17/Qt6 Widgets scaffold with CMake
  • ProfilesWindow (QMainWindow) with search, profile list, and New/Edit/Delete controls
  • Double-click in Profiles opens a SessionWindow
  • SessionWindow (QMainWindow) with QTabWidget
  • Placeholder tab content showing OrbitHub Native Surface
  • main.cpp wiring for application startup
  • Cross-platform build command guide in docs/BUILDING.md

Git:

  • Tag: v0-m0-done

Milestone 1 - Storage and CRUD

Status: Completed

Delivered:

  • SQLite integration via Qt SQL (QSQLITE)
  • Persistent profile database bootstrap (profiles table)
  • Profiles CRUD (New / Edit / Delete) in ProfilesWindow
  • Search-backed profile listing from storage
  • Double-click connect opens SessionWindow tab with selected profile name

Git:

  • Tag: v0-m1-done

Milestone 2 - Profile Details and Connect Lifecycle

Status: Completed

Delivered:

  • SQLite schema migration for profile details (host, port, username, protocol, auth_mode)
  • New ProfileDialog form for New/Edit profile workflows
  • Profiles list now shows endpoint metadata and supports search by name or host
  • Connect now loads complete profile details into SessionWindow
  • Session tab lifecycle status updates (Connecting, Connected, Failed) via non-blocking timer flow

Git:

  • Tag: v0-m2-done

Milestone 3 - Real SSH Backend and Session Controls

Status: Completed

Delivered:

  • Backend architecture introduced (SessionBackend + protocol-specific implementations)
  • Worker-thread backend execution for connection lifecycle operations
  • Real SSH process backend (ssh) with connect/disconnect/reconnect
  • Unsupported protocol backend with explicit not-implemented messaging (RDP/VNC)
  • Session tab controls: Connect, Disconnect, Reconnect, Copy Error
  • Connect-time credential flow (password prompt / private-key path selection)
  • Session event log pane with timestamps and user-friendly error mapping
  • SQLite profile schema migration for private_key_path and known_hosts_policy

Git:

  • Tag: v0-m3-done

Milestone 4 - Interactive SSH Session UX

Status: Completed

Delivered:

  • Embedded interactive SSH terminal using KodoTerm + vendored libvterm
  • Native in-terminal typing for SSH sessions (no separate input box)
  • ANSI/color rendering with selectable terminal themes (Dark, Light, Solarized Dark)
  • Cross-platform SSH auth path improvements (ssh-askpass handling and host-key policy wiring)
  • Session UX simplification: auto-connect on tab open, disconnect on tab close
  • Tab-state indicators via tab color and state suffix (Connecting, Connected, Disconnected, Failed)
  • Right-click tab menu for Disconnect, Reconnect, Theme, and Clear
  • Collapsible events panel retained as primary diagnostics surface; inline detail/status banners removed
  • Terminal behavior polish: better fixed-width font selection, cursor visibility, backspace handling, and terminal-size negotiation stability

Git:

  • Tag: v0-m4-done

Milestone 5 - RDP Fully Working

Status: Completed

Delivered:

  • Added RdpSessionBackend and wired protocol selection so RDP no longer routes to unsupported backend
  • Pivoted RDP design to embedded-only integration (no external RDP process launches)
  • Implemented embedded FreeRDP client thread with connect/disconnect lifecycle and event-loop handling
  • Added in-window RdpDisplayWidget rendering surface with frame updates from FreeRDP GDI
  • Wired direct keyboard/mouse input from the embedded RDP surface to the backend
  • Added RDP connect-time password prompt flow and settings wiring (host/port/user/password, desktop size)
  • Added explicit profile Domain support for RDP auth (with DOMAIN\username fallback parsing)
  • Updated session tab/context-menu behavior so terminal-only actions are hidden on RDP tabs
  • Implemented dynamic in-session RDP resolution renegotiation from viewport resize events
  • Enabled minimal FreeRDP client-channel build (drdynvc + disp) and channel loading for runtime resize support
  • Added RDP profile-level security mode and performance profile options, wired into FreeRDP connection settings
  • Hardened RDP lifecycle handling for disconnect/reconnect/abort flows to avoid false failure states on user-initiated stops
  • Expanded RDP error/disconnect diagnostics with richer FreeRDP code mapping and raw disconnect detail events
  • Pulled FreeRDP source for integration planning and API review

Git:

  • Tag: v0-m5-done

Milestone 6 - VNC Working (initial scope)

Status: Completed (initial scope; see gaps below)

Delivered:

  • VncSessionBackend: an original RFB (RFC 6143) client implementation against QTcpSocket -- no permissively licensed VNC client library exists to vendor the way FreeRDP was for RDP (LibVNCClient is GPLv2, gtk-vnc is LGPL but GTK-tied), so this is from-scratch protocol code, threaded like SshSessionBackend (a QObject on its own QThread driven by Qt's own async socket signals) rather than RdpSessionBackend's manual worker-thread/blocking-loop pattern
  • Full connect/disconnect/reconnect lifecycle, RFB protocol-version negotiation (3.3/3.7/3.8 handshake differences handled explicitly), VNC Authentication (DES challenge-response, using OpenSSL's classic DES API) and no-auth security types, Raw + CopyRect framebuffer decoding, keyboard (Qt key -> X11 keysym mapping) and mouse/wheel input forwarding
  • VncDisplayWidget mirroring RdpDisplayWidget's scale-to-fit rendering and input-forwarding shape
  • 19 unit tests (tests/test_vnc_session_backend.cpp): pure-function coverage (DES key prep verified against an independently documented test vector, keysym mapping, socket-error mapping) plus state-machine coverage against a scripted in-process fake RFB server (all three protocol-version handshake shapes, auth success/failure, unsupported security types, pixel-accurate Raw decoding) -- caught and fixed a real re-entrancy bug (abort() synchronously re-firing disconnected() mid-failConnection(), silently overwriting a specific error with a generic one)
  • Verified live against a real, independently implemented VNC server (TightVNC on Windows): connect with VNC Authentication, correct framebuffer dimensions and pixel data, clean disconnect, reconnect

Known gaps (explicit scope decisions, not oversights -- see issue #3 for follow-up tracking):

  • Apple's Screen Sharing authentication (Diffie-Hellman + AES, security type 30) isn't implemented, so this can't yet reach macOS's built-in VNC server -- only standard VNC Authentication (type 2) and no-auth (type 1)
  • Raw + CopyRect encodings only -- no Hextile/ZRLE/Tight compression, so bandwidth usage is higher over slow links than a full VNC client
  • No dynamic resize (connects at the server's native resolution, scaled to fit locally -- the same way RdpDisplayWidget already renders regardless of server resolution, so not a UX regression vs. RDP)
  • No remote cursor shape sync (local default cursor only)
  • No clipboard sync

Milestone 7 - Cross-Platform Protocol Hardening

Status: Completed

Delivered:

  • Validated SSH and RDP workflows on Linux, macOS, and Windows 11 (VNC is out of scope while Milestone 6 remains deferred)
  • Windows: validated the full docs/BUILDING.md toolchain end-to-end (Git/CMake/Ninja/VS Build Tools with the C++ workload/vcpkg for Qt6-OpenSSL-zlib); documented a VS Build Tools installer gotcha where the actual compiler is a "recommended", not "required", component of the VCTools workload
  • Fixed RDP keyboard input misreading punctuation keys on Linux (X11 keycode numbering was being treated as a PC/AT scancode; now uses FreeRDP's authoritative X11-keycode-to-scancode table)
  • Added RDP clipboard sync (bidirectional, plain text) and RDP cursor/pointer shape sync (resize handles, text I-beam, etc. instead of a static arrow)
  • Fixed Tab/Shift+Tab being intercepted by local UI focus navigation instead of reaching SSH/RDP sessions
  • Fixed RDP key auto-repeat being dropped, so holding a key only ever sent a single keystroke to the remote machine
  • Windows-specific RDP fixes: a crash on every connect attempt (FreeRDP's signal-handling critical section was never initialized) and a host resolution failure on every connect, including literal IP addresses (Winsock was never initialized via WSAStartup)
  • Windows: automatic build-time deployment of Qt's platform/SQL-driver plugins and their runtime DLL dependencies, and marked the executable as a GUI (WIN32) app to remove a stray console window behind the UI
  • Windows and macOS: proper native app icon embedding (Windows .rc/.ico resource; macOS .app bundle with .icns), replacing the generic default icon previously shown for the built executable/bundle
  • macOS: fixed Edit/New Profile dialog form fields collapsing to sizeHint width due to the platform-default QFormLayout field growth policy

Git:

  • Tag: Pending user approval (v0-m7-done)

Milestone 8 - Profile and Session UX Completion

Status: Completed

Delivered:

  • Added profile tags field to storage + schema migration and profile editor UX
  • Added profile folder_path field + nested folder/subfolder profile view mode
  • Added profile tree context actions (New Folder, New Connection) and drag-to-folder profile moves with persistence
  • Added Help -> About OrbitHub dialog with third-party library inventory and MIT/Apache-2.0 license links
  • Extended profile search to include tags/folder path and added profile sort controls (Name, Protocol, Host)
  • Persisted profile list UX preferences (search text, view mode, protocol/tag filters, sort order) across app restarts
  • Added protocol-aware profile validation/normalization for SSH/RDP/VNC (repository + dialog)
  • Improved profile form protocol UX hints and SSH private-key path validation
  • Added session events filtering and tab-context actions (Show/Hide Events, Copy Events, Clear Events)
  • Added session diagnostics QoL: severity quick-filter (All/Warnings/Errors) and Export Events action
  • Persisted session UI defaults (terminal theme, events panel visibility) for new tabs/windows
  • Added profile quick filters (Protocol, Tag) with persistence to speed profile browsing

Validation:

  • Local build verification passed (cmake --build build)
  • No automated tests are currently configured in CTest

Git:

  • Tag: Pending user approval (v0-m8-done)

Milestone 9 - Packaging and Distribution

Status: Completed

Delivered:

  • Linux .deb (packaging/linux/build-deb.sh) and Flatpak (packaging/flatpak/build-flatpak.sh) packages, both verified installed and launched with working SSH/RDP
  • Renamed the app's reverse-DNS identity from io.orbithub.OrbitHub to org.darksingularity.OrbitHub (desktop file, AppStream metainfo, Flatpak manifest, macOS bundle identifier) to reflect a domain actually owned by the project
  • Fixed Linux taskbar/panel pin matching (StartupWMClass) so a pinned launcher merges with its running window instead of creating a duplicate entry
  • Replaced the stale, mismatched hand-authored launcher SVG with PNG icons rendered directly from the app's own createOrbitHubAppIcon() at each hicolor theme size
  • Windows installer via Inno Setup (packaging/windows/orbithub.iss, packaging/windows/build-installer.ps1), verified installed silently and launched cleanly with no crash events
  • macOS .dmg via cmake --install + macdeployqt + hdiutil (packaging/macos/build-dmg.sh), verified installed and launched after fixing:
    • a launch crash caused by macdeployqt invalidating the code signature (fixed with ad hoc re-signing)
    • a missing-library crash caused by the Linux-only $ORIGIN rpath token and vendored dylibs installing outside the .app bundle (fixed with APPLE-specific @executable_path/Contents/Frameworks layout)
    • the dmg showing the generic disk icon instead of the app icon
  • README and docs/BUILDING.md Packaging sections documented for all three platforms

Validation:

  • All three installers built, installed, and launched successfully with working SSH/RDP sessions
  • Code signing is ad hoc only (no purchased Apple Developer ID or Windows code-signing certificate), so macOS Gatekeeper and Windows SmartScreen still show first-run warnings by design

Git:

  • Tag: v0-m9-done
  • Release: v2026.9.8 (v2026.9.8 tag, installers for Windows/Linux/macOS)
  • Release: v2026.9.8.2 — same-day patch fixing RDP TLS certificate verification (was fully disabled) and preparing Flatpak packaging for Flathub submission
  • Release: v2026.9.8.3 — same-day patch adding an in-app User Guide and standalone User Guide PDF
  • Release: v2026.9.14 — fixes distorted RDP text on HiDPI monitors and reduces RDP resize-related display glitches
  • Release: v2026.9.14.2 — same-day patch fixing RDP display corruption (missing/misplaced taskbar) after resizing the session window (the client never resized its own display buffer for channel-driven RDP resizes)
  • Release: v2026.9.15 — adds Import/Export for profile lists (File menu)

Milestone 10 - v1.0 Stabilization

Status: Planned

Planned Scope:

  • Run final regression and acceptance testing across all protocols
  • Resolve release-blocking defects
  • Finalize docs and publish v1.0 release notes/checklist