Internal
Public Access
Tight's JPEG sub-mode (previous commit) links libjpeg-turbo directly. Adds it to docs/BUILDING.md for all three platforms (apt libjpeg-turbo8-dev, brew jpeg-turbo, vcpkg libjpeg-turbo:x64-windows) and to the .deb package's Depends: line (libjpeg-turbo8). No changes needed for Windows (the Inno Setup script already wildcards *.dll) or macOS (macdeployqt bundles non-system dylibs automatically). Left the Flatpak manifests unchanged on the assumption that the KDE runtime already bundles libjpeg-turbo as a standard Qt JPEG-plugin dependency -- flagged in PROGRESS.md as worth confirming next time a Flatpak build actually runs, since that wasn't independently verified here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
18 KiB
18 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) withQTabWidget- Placeholder tab content showing
OrbitHub Native Surface main.cppwiring 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 (
profilestable) - Profiles CRUD (New / Edit / Delete) in
ProfilesWindow - Search-backed profile listing from storage
- Double-click connect opens
SessionWindowtab 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
ProfileDialogform 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_pathandknown_hosts_policy
Git:
- Tag:
v0-m3-done
Milestone 4 - Interactive SSH Session UX
Status: Completed
Delivered:
- Embedded interactive SSH terminal using
KodoTerm+ vendoredlibvterm - 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-askpasshandling 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, andClear - 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
RdpSessionBackendand wired protocol selection soRDPno 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
RdpDisplayWidgetrendering 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
Domainsupport for RDP auth (withDOMAIN\usernamefallback 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 againstQTcpSocket-- 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 likeSshSessionBackend(aQObjecton its ownQThreaddriven by Qt's own async socket signals) rather thanRdpSessionBackend'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
VncDisplayWidgetmirroringRdpDisplayWidget's scale-to-fit rendering and input-forwarding shape- 41 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/Hextile/ZRLE/Tight decoding including a ZRLE zlib-stream-persistence test across two separateFramebufferUpdatemessages, a Tight stream-reset-flag test, cursor/ clipboard round trips) -- caught and fixed a real re-entrancy bug (abort()synchronously re-firingdisconnected()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, live cursor-shape and clipboard-send checks. That particular server consistently chose Raw for actual framebuffer content regardless of which compression encodings were announced, so Hextile/ZRLE/Tight's real-world decode path isn't independently confirmed live -- the unit tests are the primary correctness evidence for those
- Per-tab VNC-only display mode toggle (tab-bar right-click ->
Display Mode):Scale to Fit(default, matches RDP's behavior) orActual Size (Scrollbars)-- renders the remote framebuffer at its native pixel size inside aQScrollAreaso text isn't shrunk, at the cost of needing to scroll to see the whole screen. ReusesVncDisplayWidget::renderRect()'s existing scale-to-fit math unchanged: it degenerates to an exact 1:1 mapping once the widget's own bounds are fixed to the remote's size, so no separate rendering path was needed. Persisted across sessions like the terminal theme preference. - Robustness fix: an unrecognized
FramebufferUpdaterectangle encoding used to abort the connection generically;kAnnouncedEncodingsis now the single source of truth for whatSetEncodingsannounces and what the rectangle-dispatchswitchcan decode, with a regression test pinning that every announced encoding has a working case - Clipboard sync (
ServerCutText/ClientCutText, Latin-1 only -- no Unicode extension) in both directions - Remote cursor shape sync via RFB's Cursor pseudo-encoding, mirroring
RdpDisplayWidget's cursor handling inVncDisplayWidget - Hextile, ZRLE, and Tight compression encodings, in addition to Raw +
CopyRect -- meaningfully reduces bandwidth over slower links versus Raw
alone; Tight in particular is the encoding most real VNC servers prefer
when the client offers it. Pure tile/pixel decode logic (including
Tight's three filters -- Copy, Palette, Gradient) lives in
src/vnc_pixel_codecs.h/.cpp, kept separate from the wire-sequencing state machine so it's unit-testable without a socket. ZRLE and Tight's Basic mode share the same "persistent zlib stream(s), decompress in-memory, decode synchronously" approach (Tight has 4 independent streams selected per-rectangle, individually reset via the compression-control byte's low 4 bits). Tight's JPEG sub-mode decodes via libjpeg-turbo directly (find_package(JPEG REQUIRED)->JPEG::JPEG), notQImage's own JPEG plugin, to avoid a packaging-dependent runtime failure mode. ZRLE/Tight linkZLIB::ZLIB(found via a fresh top-levelfind_package(ZLIB REQUIRED), independent of whether vendored FreeRDP's own internal zlib usage stays enabled) - 41 unit tests total, 15 of them for Hextile/ZRLE/Tight specifically,
including a ZRLE zlib-stream-persistence test across two separate
FramebufferUpdatemessages and a Tight stream-reset-flag test proving the low 4 control-byte bits actually tear down and reinitialize the targeted stream rather than erroring out on stale state
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)
- Tight's Basic compression mode always assumes zlib-compressed payloads; the real protocol permits the server to skip compression for very small (filtered byte count under ~12) payloads, which this decoder doesn't special-case (the exact trigger/wire-signaling for that couldn't be verified with confidence against the RFC text alone). In practice this only affects rare, tiny rectangles -- solid or near-solid tiny areas are virtually always sent as Fill instead -- and fails that one rectangle's decode cleanly (disconnects with a clear error) rather than silently misinterpreting it
- Tight's Gradient filter is implemented from RFC 6143's description but is the least exercised/confirmed of the three filters against a real server in this pass (most real-world Tight traffic uses Copy or Palette)
- Packaging for the new
libjpeg-turbodependency: added todocs/BUILDING.md(apt/brew/vcpkg) and the.debcontrol file'sDepends:(libjpeg-turbo8). The Windows Inno Setup script already wildcards*.dllso no change was needed there, and macOS'smacdeployqt-based bundling picks up non-system dylibs automatically. The Flatpak manifests (packaging/flatpak/*.yml) were left unchanged on the assumption thatorg.kde.Platform/Sdk6.11 already bundles libjpeg-turbo (a standard Qt JPEG-plugin dependency) -- worth confirming the next time a Flatpak build is actually run, since it wasn't independently verified here - No dynamic resize (connects at the server's native resolution; the
Scale to Fit/Actual Sizetoggle changes how that fixed resolution is displayed locally, not what resolution is requested from the guest -- VNC has no equivalent of RDP's MS-RDPEDISP for that)
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.mdtoolchain 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/.icoresource; macOS.appbundle with.icns), replacing the generic default icon previously shown for the built executable/bundle - macOS: fixed Edit/New Profile dialog form fields collapsing to
sizeHintwidth due to the platform-defaultQFormLayoutfield growth policy
Git:
- Tag: Pending user approval (
v0-m7-done)
Milestone 8 - Profile and Session UX Completion
Status: Completed
Delivered:
- Added profile
tagsfield to storage + schema migration and profile editor UX - Added profile
folder_pathfield + 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 OrbitHubdialog 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) andExport Eventsaction - 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.OrbitHubtoorg.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
.dmgviacmake --install+macdeployqt+hdiutil(packaging/macos/build-dmg.sh), verified installed and launched after fixing:- a launch crash caused by
macdeployqtinvalidating the code signature (fixed with ad hoc re-signing) - a missing-library crash caused by the Linux-only
$ORIGINrpath token and vendored dylibs installing outside the.appbundle (fixed withAPPLE-specific@executable_path/Contents/Frameworkslayout) - the dmg showing the generic disk icon instead of the app icon
- a launch crash caused by
- README and
docs/BUILDING.mdPackaging 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.8tag, 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