2026.2.1 (2026-06-03) Benoît Cortier <bcortier@devolutions.net>

* dgw: serve standalone web app and recording player static assets  
  The standalone web application and the recording player loaded their
  main page but failed to load any static assets (JS, CSS, fonts), which
  returned HTTP 500. As a result both UIs were effectively broken.
  Requests for sub-resources under /jet/webapp/client/ and /jet/jrec/play/
  now resolve correctly, restoring the standalone web application and the
  recording player.

2026.2.0 (2026-06-02) Benoît Cortier <bcortier@devolutions.net>

Several newly introduced Gateway/Agent surfaces remain experimental and are
controlled by debug.enable_unstable (notably /jet/tunnel/*, and KDC
proxy credential-injection destination handling). Related infrastructure such
as core forwarding, KDC real-destination proxying, and Agent Tunnel runtime
activation is configured independently and may remain active outside this flag.
* dgw: refuse JREC push when recording storage is full 
* agent,gateway: transparent routing through agent tunnel (experimental)         
* installer: add install-time certificate checks 
* dgw: Kerberos-based credential injection (experimental)  
* dgw: improved network scans  
* jetsocat: embed Windows icon and version metadata  
* agent: add OEM code page transcoding in Devolutions Agent   

2026.1.2 (2026-04-18) Benoît Cortier <bcortier@devolutions.net>

* dgw,agent: agent self update and scheduled updates    
  - Devolutions Agent self-update using shim executable.
  - Scheduled updates.
  - /jet/update endpoint improvements (moved params to request body, deprecated query param).
  - New /jet/update/schedule endpoint for controlling on-machine update scheduling.
  - New GET endpoints for both /jet/update and /jet/update/schedule. Agent now provides new update_status.json for querying product update and schedule status.
* jetsocat: --log-term was logging to stdout instead of stderr 
  The --log-term flag was routing log output through stdout, polluting the MCP stdio JSON-RPC channel and any other stdout-based protocol. Fixed to use stderr, which is the correct descriptor for diagnostic output.
* jetsocat: always send JSON-RPC message on MCP proxy backend disconnect 
  When the backend MCP process disconnects, the proxy now always sends a protocol-level message to the client before exiting, instead of silently closing the stdio channel:
  - SendError::Fatal (write to broken backend): JSON-RPC error response (-32099) with the pending request id.
  - ReadError::Fatal with a pending request: JSON-RPC error response (-32099) so the client can correlate it with the outstanding request.
  - ReadError::Fatal with no pending request: a $/proxy/serverDisconnected notification so the client is informed even without an active request.
* jetsocat: properly JSON-escape error details in MCP proxy JSON-RPC error responses 
* dgw: report disk space when recording dir does not exist yet   
  When the recording folder has not been created yet, GetDiskFreeSpaceExW / statvfs failed with OS error 3 because the path did not exist, causing recordingstoragetotalspace and recordingstorageavailablespace to be absent from the heartbeat response. Fix by walking up to the nearest existing ancestor before querying disk space.
* dgw: add warn logs to shadow recording error paths   
  Added warn! logs to all 4 InternalError (close code 4002) branches in the shadow_recording handler. Previously, these error paths silently closed the WebSocket with no diagnostic output, making production debugging nearly impossible.
* dgw: resolve WER APIs dynamically to support Windows Server 2016   
  WerRegisterExcludedMemoryBlock is absent from wer.dll on Windows Server 2016 RTM (NT 10.0.14393). The static import introduced in v2026.1.1 caused the Windows loader to refuse starting DevolutionsGateway.exe on those hosts. Replaced with runtime resolution via GetModuleHandleW / GetProcAddress, cached in a OnceLock. The binary now starts on any Windows 10/Server 2016 build and silently skips WER dump exclusion when the API is unavailable.
* agent: configure features correctly during silent install by passing feature states via CustomActionData  
* agent: propagate registry open errors during agent install detection  
* dgw: overhaul Linux RPM/DEB packaging   
  RPM: bundle the systemd unit file directly (eliminating the service register call), ship a systemd preset file so the service is enabled on fresh RHEL/Rocky install, use systemd-rpm-macros for correct lifecycle semantics, fix prerm/postrm scripts, harden config directory permissions to 750. DEB: mirror RPM service lifecycle semantics (enable on fresh install but do not start; try-restart on upgrade), harden config directory permissions to 750, add Description= to unit file. Both packages print a post-install message directing the admin to configure and start the service.

2026.1.1 (2026-04-01) Benoît Cortier <bcortier@devolutions.net>

* installer: warn on, instead of hiding, unvalidated certificates   
  When searching for a certificate in the system store we call
  X509Certificate2Collection.Find with the validOnly parameter set to
  true.
  validOnly
  Boolean
  true to allow only valid certificates to be returned from the search;
  otherwise, false.
  The performs basic validation, and only returns valid certificates.
  However, the result is confusing for users as they don't realize that
  the certificate they are searching for is invalid, they think that the
  search isn't working.
  Instead, we now return all certificates but if the certificate is
  determined to be invalid, we flag it in the UI with a warning icon and a
  text explanation.
* installer: add a German localization  
* jetsocat: add warning field to doctor diagnostic output 
  Adds support for surfacing warnings in the doctor tool's diagnostic
  output, allowing external tools to distinguish between complete success,
  success with warnings, and failure.
  The diagnostic JSON output now includes an optional "warning" field, and
  the human-readable output displays a warning emoji (⚠️) instead of a
  success checkmark (✅) when warnings are present.
  This enables better integration with external monitoring and diagnostic
  tools that need to detect and report warning conditions even when the
  overall diagnostic succeeds.
* jetsocat: add SAN and EKU diagnostics to doctor module  
  Add certificate extension checks mirroring the gateway's TlsVerifyStrict
  validation. Each TLS backend (rustls, openssl, schannel) now runs two new
  diagnostics on the end-entity certificate:
  - checksanextension: verifies the Subject Alternative Name extension is present
  - checkserverauth_eku: verifies the Extended Key Usage includes serverAuth
* dgw: add periodic keyframe forcing for improved seekability   
* jetsocat: detect missing intermediate certificate in doctor   
  When a TLS server presents only the leaf certificate (or leaf + root CA
  but no intermediate), clients fail with an opaque "unknown issuer" error
  that is hard to diagnose.
  The doctor command now performs a structural analysis of the presented
  chain before invoking the trust engine:
  - If the chain contains only a leaf and no certificate whose Subject
  matches the leaf's Issuer, a warning "an intermediate certificate is
  likely missing" is attached to the read-chain diagnostic.
  - On chain verification failure (UnknownIssuer /
  CERTTRUSTISPARTIALCHAIN / CERTTRUSTISUNTRUSTEDROOT), actionable
  help "intermediate certificate is likely missing" is shown instead of
  the generic "unknown issuer" message.
  - Omitting the root CA (the normal server configuration) does not
  trigger the warning.
  - Self-signed (root-only) certificates are also not flagged.
* dgw: encrypt in-memory credentials at rest with ChaCha20-Poly1305   
  Add ChaCha20-Poly1305 encryption for credentials stored in the
  credential store. Passwords are encrypted at rest with a randomly generated 256-bit
  master key held in a protected page.
  The page protection hardening is performed using the best available OS
  hardening in a best-effort basis:
  - Windows: VirtualLock, guard pages (PAGENOACCESS), PAGEREADONLY after
   write, WerRegisterExcludedMemoryBlock for WER crash report exclusion.
  - Linux:   mlock, guard pages (PROTNONE), PROTREAD after write,
            madvise(MADV_DONTDUMP) for core dump exclusion.
  - All:     zeroize-before-free on drop; plain heap fallback with
            zeroize-on-drop on unsupported platforms.
  In concrete terms: this protects users from leaking important secrets in
  the event of a memory dump captured for debugging purposes.
* dgw: fix adaptive frame skipping during EOF waits in session shadowing   
  Fixes video playback freezing permanently during live session shadowing.
  After brief pauses in the recording stream (e.g., during network hiccups
  or slow file writes), the shadow player would stop rendering new frames
  entirely, requiring a session restart.
  With this fix, shadow sessions now recover gracefully from temporary
  recording pauses, maintaining smooth video playback throughout the
  session.
* installer: prevent issues with deferred properties containing semi-colons  
* dgw: add codec-aware VP9 keyframe detection  
  Add VP9 keyframe detection alongside existing VP8 support, based on
  the VP9 bitstream specification (profiles 0-3). Thread the VpxCodec
  type through the iterator and block tag layers so keyframe checks use
  the correct codec-specific logic. Set VpxEncoderPreset::BestPerformance
  on the re-encoding encoder for improved throughput during session shadowing.
* dgw: improve unified shutdown correctness  
  Replace scattered shutdown mechanisms with a single tokio::sync::watch
  channel as the source of truth. Handle task now signals ClientDisconnected
  on client disconnect and uses select! on ws_frame.next() for shutdown
  awareness. Bridge task is aborted on webm_stream exit to prevent
  control_task from hanging indefinitely.
* dgw: update cadeau native library to v2026.3.13.0    
* dgw: fix service subcommand parsing   
* dgw: fix minimum glibc version in deb manifest   
  We cross-compile against an ubuntu-18.04 sysroot (via cbake), which
  ships glibc 2.27, not 2.31.
* dgw: fix RPM webapp directories installed under wrong names   
  fpm installs a source directory by name inside the destination when
  given a bare directory path. Specifying explicit target paths ensures
  webapp/client and webapp/player are consistent with the DEB package.
* jetsocat: fix schannel doctor backend 
  Set endentityinfo in schannelreadchain for the leaf certificate, so
  that cert checks work when loading a chain from a PEM file.
* dgw: fix RPM webapp directories installed under wrong names   
  fpm installs a source directory by name inside the destination when
  given a bare directory path. This is identical to #1717 but targets the
  currently active code path found in tlk.ps1.
* dgw: reduce log noise for missing recording storage disk   
  When the recording storage disk cannot be found during a heartbeat or
  preflight check, only the first occurrence is now logged at WARN.
  Subsequent repeated occurrences are downgraded to DEBUG until the disk
  becomes available again, at which point the condition can surface at
  WARN once more. The recording path is included in the log event for
  context.
* dgw: support network drives and UNC paths for recording storage space on Windows   
* dgw: use statvfs for recording storage space on Unix   
  Replaces the sysinfo disk-enumeration approach on Linux/macOS with a
  direct statvfs(2) call against the configured recording path. This fixes
  incorrect or missing space values for network filesystems (NFS,
  CIFS/Samba) and any mount point the previous heuristic could not
  resolve.
* jetsocat: enable detect-proxy for Windows jetsocat builds  

2026.1.0 (2026-02-23) Benoît Cortier <bcortier@devolutions.net>

* agent-installer: deploy desktop agent in main feature  
* agent: UX improvement for desktop agent app  
* agent-installer: auto launch desktop app on install  
* dgw: add CredSSP certificate configuration keys   
  Add optional CredSspCertificateFile, CredSspPrivateKeyFile and CredSspPrivateKeyPassword
  configuration keys allowing usage of a different certificate for CredSSP
  credential injection instead of the main TLS certificate. When unset,
  the existing TLS certificate is used (no behavior change).
* dgw: generate self-signed certificate when no TLS cert is configured for CredSSP   
  When neither a CredSSP-specific certificate nor a main TLS certificate
  is configured, automatically generate a self-signed certificate for
  CredSSP credential injection.
* agent-installer: specify ARM64 platform for ARM64 agent installer  
* agent-installer: cleanup of agent installer  
* dgw: improve real-time performance of session shadowing    

2025.3.4 (2026-02-04) Benoît Cortier <bcortier@devolutions.net>

* dgw: redact passwords in preflight API debug logs    
  Passwords in provision-credentials preflight requests are now redacted
  when logged at DEBUG level, preventing credential leakage in logs. The
  redaction applies to all password fields recursively, replacing them
  with "REDACTED" while preserving other request details for
  debugging.
* agent: add debug updater overrides   
  Adds debug configuration switches for the updater so developers can test
  local productinfo and packages:
  - Supports overriding productinfo URL (including file://) and validates
  CDN URLs by default.
  - Allows opt-in unsafe URLs for local testing and optional skipping of
  hash/MSI signature validation.
  - Productinfo loader and package downloader now handle file:// sources
* installer: allow untrusted certificates for key downloads   
  Using the installer, the user has the option to download the provisioner
  public key direct from a DVLS instance. However, if the DVLS certificate
  was not trusted this would fail with a nondescript error message
  ("failed to send request").
  Now, the user will be prompted to accept an untrusted certificate.
  Certificate exceptions are serialized in a semi-colon delimited text
  string in the form:
* webapp: update SSH package with deprecated algorithm and keyboard interactive auth support    
  Update @devolutions/web-ssh-gui from 0.4.0 to 0.6.2 with the following
  improvements:
  - Add Keyboard_Interactive authentication mode for SSH connections
  - Support for deprecated SSH algorithms (for legacy server
  compatibility)
  - Fix deadlock between terminal visibility and host key verification
  - Library now emits connected status when WebSocket connects, allowing
  users to see and respond to host key verification prompts
* dgw: add support for credential injection for RDCleanPath   
  This allows web clients to benefit from the proxy-based credential injection features.
* agent: RDM messages and pipe passthrough logic    
  Adds RDM (Remote Desktop Manager) message handling capabilities to
  devolutions-session, enabling bidirectional communication between the
  agent and RDM through the NOW protocol over the named pipe.
* webapp: upgrade to Angular 20 and PrimeNG 20   
  Upgrades the standalone webapp to Angular 20 and PrimeNG 20. This keeps the
  frontend on current, supported framework versions and enables continued UI
  improvements with the latest PrimeNG components.
* dgw,agent: add HTTP/SOCKS proxy configuration support    
  Adds configurable HTTP/HTTPS/SOCKS4/SOCKS5 proxy support for outbound
  requests in both Gateway and Agent. Proxy settings can be configured
  manually or auto-detected from environment variables (HTTP_PROXY,
  HTTPSPROXY, NOPROXY) or system settings (per-user and machine-wide
  settings with WinHTTP fallback on Windows, /etc/sysconfig/proxy on
  RHEL/SUSE systems, SCDynamicStoreCopyProxies() on macOS).
  This replaces reqwest's system-proxy feature with the proxy_cfg crate
  for better system integration and per-URL proxy selection, improving
  support for PAC files and complex enterprise proxy environments.
* agent: add window recording support via now proto dvc    
  Adds window recording support to the Devolutions Agent. The
  implementation uses Windows event hooks to receive foreground window
  change notifications and optional polling to detect title changes within
  the same window.
* agent: improve error reporting when checking for updates   
* dgw: improve system store certificate resolver error logging    
  The system store certificate resolver now accumulates and displays
  detailed key acquisition errors at the default log level when no
  suitable certificate is found. Previously, these errors (such as "keyset
  does not exist" / error code 0x80090016) were only visible at DEBUG
  level, making it difficult to diagnose issues like missing private key
  permissions for the NETWORK SERVICE user.
  The error message now includes specific failure details for each
  certificate attempt, including both key acquisition and signing key
  creation failures.
* installer: allow certificate passwords to contain single quotes  
* dgw: downgrade benign client disconnects from ERROR to DEBUG    
  Reduces log noise by treating common socket disconnections (BrokenPipe,
  ConnectionReset, UnexpectedEof) as benign events during HTTP/HTTPS
  serving and TLS handshake. These disconnects typically occur from health
  checks, port scanners, aborted browser requests, or early connection
  termination, and do not indicate server faults.
  ERROR logs now only appear for genuine server issues, making it easier
  to identify actionable problems in production deployments.
* dgw: self-signed TLS certificate generation of the Docker image build   
  Fixes this error:
  `
  Get-Content: Cannot find path '/tmp/gateway-{hostname}.pem' because it does not exist.
  Exception: Empty certificate chain!
  `
  Hit when generating the self-signed TLS certificate generation in the Docker entrypoint.
* dgw: honor TCP_PORT in Linux container entrypoint   
  Fixes an issue where the TCP_PORT environment variable was ignored by
  the Linux Docker entrypoint.
  Even when TCP_PORT was set, the gateway continued to use the default TCP
  port.
  This change ensures the gateway now correctly applies the configured
  TCP_PORT value at startup.
* agent: add RDM multi-instance support for Jump messages    
  Add RDM multi-instance support for Jump messages (separate named pipe
  for each RDM instance in session)
* dgw: add ARM64 Docker image support    
  Adds native ARM64 Docker images for Devolutions Gateway, enabling
  deployment on ARM-based devices like Raspberry Pi and AWS Graviton
  instances with full native performance. Multi-arch manifests
  automatically select the correct image for the user's platform.

2025.3.3 (2025-12-02) Benoît Cortier <bcortier@devolutions.net>

* webapp: update VNC and RDP clients   
  * VNC: Prevent a custom pixel format from being set if Tight JPEG or _Tight
  PNG_ is enabled.
  * VNC: Fixed an issue where Zlib encoding was always advertised to the
  server, regardless of the chosen ARD quality.
  * RDP: Fixed an issue where the clipboard data was not sent to the server
  right after the connection.
  * RDP: Fixed the lastSentClipboardData being null in the
  onForceClipboardCallback.
  * RDP: Added human-readable descriptions for RDCleanPath errors.
  * VNC: Update cryptographic libraries for VNC.
* installer: download public key from DVLS  
* installer: allow CLI generation on release builds  
* jetsocat: add concurrent reads support for MCP proxy    
  Refactor MCP proxy to support server-initiated messages (notifications,
  progress updates, and server -client requests) by enabling concurrent
  reads from both client and server.
* dgw: TLS thumbprint anchoring    
  Allow "unsecure" TLS if the client provides a thumbprint and the peer
  certificate matches it.
* agent: implement DVC remote exec detached mode   ) 
  Adds fire-and-forget remote execution via the now proto DVC.
  Previously, all execution types (except Run) waited for the process exit
  code and tracked the execution session, but this behavior is not always
  what the user expects. This PR changes that and adds an option to
  specify if fire and forget mode is needed (return result right after
  process is spawned.
* agent,dgw: add Hub Service auto-updater support   
* dgw: add multi-provider AI Gateway   
  Adds an experimental AI Gateway feature that provides a unified proxy
  for multiple AI provider APIs through Devolutions Gateway. This enables
  centralized API key management, consistent authentication, and
  simplified access to various AI services from a single endpoint.
  Supports seven providers with OpenAI-compatible and
  provider-specific endpoints, featuring transparent proxying, SSE
  streaming support, and flexible configuration through both JSON config
  and environment variables.
  Supported providers:
  - Mistral AI (cloud API)
  - OpenAI (cloud API)
  - Anthropic Claude (cloud API with custom message format)
  - OpenRouter (unified multi-provider API)
  - Azure OpenAI (deployment-based Azure service)
  - Ollama (local, OpenAI-compatible, optional auth)
  - LM Studio (local, OpenAI-compatible, optional auth)
  Requires enable_unstable: true in debug configuration.
* agent: migrate from productinfo.htm to productinfo.json format   
  Replaces the legacy flat key-value productinfo.htm format with a
  structured JSON format that provides better organization and
  extensibility. The new format supports multiple release channels
  (Current, Beta, Update, Stable) and includes explicit architecture and
  file type metadata.
* jetsocat: detect broken pipe and stop MCP proxy gracefully   
  When the MCP server connection breaks (process died, pipe closed), the
  proxy now detects this and stops forwarding requests instead of
  continuing to fail on each subsequent request.
* dgw: display the full trace for forward errors   
* installer: improve debouncer robustness, legibility of port check result  
* installer: update localization  
* dgw: [breaking] switch traffic audit IDs from INTEGER to ULID    
  Replace INTEGER PRIMARY KEY with 16-byte BLOB (ULID) for traffic audit
  event IDs to avoid overflow issues with persisted, ever-increasing IDs.
  - Auto-detect old INTEGER schema via PRAGMA table_info and reset
  database
  - Store ULIDs as 16-byte BLOBs (lexicographically sortable)
* agent: improve productinfo.json parsing with lenient error handling   
* webapp: fix TS errors on invalid config   
* installer: fix UI at high scaling factors  
* installer: fix broken hyperlinks  
* installer: fix a (handled) NRE that was nonetheless annoying in debug  
* installer: avoid crashes on server core  
* installer: add missing file to csproj  
* installer: UI glitch caused by tab stops  
* installer: public key action pick up downloaded file  
* dgw: fix a bug preventing mstsc to work with the RDP proxy   
* dgw,agent: improve systemd integration    
  Update ceviche to 0.7.0 which improves systemd integration.
  Here is the new strategy:
  - pkg-config detection: We query pkg-config --variable=systemdsystemunitdir systemd
  to get the distribution's preferred location. This works on most modern
  systems that have systemd development packages installed.
  - Fallback probing: If pkg-config is unavailable or doesn't return a
  result, we probe common directories in order:
    - /usr/lib/systemd/system
    - /lib/systemd/system
  This fixes installation issues on RHEL-based distributions where systemd
  units are located in /usr/lib/systemd/system instead of /lib/systemd/system.

2025.3.2 (2025-10-01) Benoît Cortier <bcortier@devolutions.net>

* dgw: support jet_reuse claim in JREC tokens    
* jetsocat: add coloring control for log output   
  Add --color flag with support for 'always', 'never', and 'auto' modes.
  Respects standard environment variables (NOCOLOR, FORCECOLOR, TERM).
* jetsocat: improve optional flag handling and error reporting   
  Improves the handling of optional command-line flags in jetsocat by
  replacing direct flag access with proper error handling: missing
  optional flags are handled gracefully while invalid flag values still
  produce clear error messages.
* dgw: cleaner log message for listener init   
* dgw: split TlsVerifyStrict warning for absent and false   
* dgw: retrial logic when binding the listeners    
  The listener binding will be reattempted a set amount of time when a
  transient error is hit, such as "address already in use".
* jetsocat: resolve channel open to start tight race condition    
* webapp: VNC connect for "None" authentication  
* jetsocat: make the MCP proxy non-intrusive    
  The MCP proxy was previously handling the initialize request itself and
  returning a response instead of forwarding it to the target MCP server.
  It also intercepted notifications/initialized and logging/setLevel
  without passing them through.
  Additionally, any unknown methods were being answered with an error
  response, even though the actual server might support them.
  This change forwards all requests and notifications directly to the
  server to ensure correct behavior and compatibility.
## 2025.3.1 (2025-9-13)
* jetsocat: missing newline after MCP proxy JSON-RPC responses   
## 2025.3.0 (2025-9-12)
* dgw: emit syslogs and Windows events for important events    
  Easier auditability of Devolutions Gateway service by emitting system-wide logs.
* webapp: implement MVP for self-contained session URLs   
  Introduced support for launching sessions directly from specially crafted URLs.
  These URLs include all necessary information to immediately initialize and
  (optionally) auto-connect a session upon opening.
  New query parameters:
  - config: Encoded session configuration data
  - autoconnect: If set to true, the session starts automatically
  - protocol: Specifies the protocol to use (currently only rdp is supported)
* webapp: support clipboard for SSH and Telnet clients    
* dgw: (Unstable) basic network monitoring    
  Introduces an endpoint monitor that checks the uptime of a list of hosts
  provided through a remotely-submitted configuration file. The monitor
  results are saved to a temporary in-memory buffer and can be fetched by
  means of a REST endpoint.
  The monitor system is structured as an agent, meant to be driven by a
  third party (for example our DVLS), so the configuration is ephemeral, and
  monitor results are deleted from the buffer after being fetched.
  Gateway is not itself the source of truth for the monitor configuration,
  and it does not persist the log entries.
  Two authenticated endpoints are introduced:
  - POST /jet/net/monitor/config
  - POST /jet/net/monitor/log/drain
* webapp: add fallback screen for unsupported browsers   
* dgw: keep records of traffic transferred via JMUX tunnels    
* dgw: implement traffic audit claim/ack HTTP endpoints    
  Add two new endpoints for external traffic audit integration:
  - POST /jet/traffic/claim - Claim events with lease-based locking
  - POST /jet/traffic/ack - Acknowledge processed events
* agent-installer: rename the session feature and make it available by default  
* agent: minimalist "About" window for tray icon   
* jetsocat: MCP proxy   
  Example usage:
  `shell
  echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jetsocat mcp-proxy - https://learn.microsoft.com/api/mcp
  `
* jetsocat: add "jmux" alias for jmux-proxy command   
* jetsocat: expand simple pipe names   
  Add automatic path expansion for np:// and np-listen:// schemes:
  - Windows: simple names expand to ./pipe/<NAME>
  - Unix: simple names expand to /tmp/<NAME>
* webapp: granular JPEG Quality option instead of explicit TightLow and TightHigh pseudo-encodings   
* webapp: add color format selector for VNC session   
  Allow the user to tune the session quality more deeply
  (e.g, lower image quality if the network is slow).
* agent: in RDP extension, add PowerShell server mode support   
* Improve container image for Azure Web App usage  
* webapp: improved error handling in remote desktop clients   
* webapp: [breaking] add manual clipboard mode for RDP, VNC and ARD   
  The original auto clipboard mode, can now be enabled/disabled in the connection form.
  It's available only for browsers based on Blink engine (e.g.: Chrome).
  For others, auto clipboard mode is always disabled.
  When disabled, two new buttons are showed in the toolbar: Save Clipboard and Send Clipboard.
  These buttons allow the user to manually send the content of the client host clipboard, or receive from
  the server clipboard.
  Note that Firefox used to have a partially working autoclipboard mode, but it was
  completely removed because the cases where it failed were confusing more than helpful.
  The auto clipboard mode is the most convenient, but the manual clipboard mode
  has a predictable behavior on all platforms.
* webapp: improve clipboard interaction for outdated versions of the Firefox browser   
* webapp: disable clipboard in non-secure context   
* webapp: incorrect user domain parsing for UPN format    
  Fix username parsing logic to correctly handle UPN and down-level
  formats.
  Only splits DOMAIN\user format; preserves user@domain.com as-is.
* agent: change PowerShell exec session run params   
* agent: remove command echo for batch(cmd) execution  
* agent: hide console window for exec sessions with IO redirection  
* agent: suppress ANSI escape codes in pwsh output  
* player: add autoplay attribute to WebM video player   
  Fixes issue where recordings were not auto-starting when embedded in
  iframes
  DGW-296
* agent-installer: add tun2socks.exe and wintun.dll to Devolutions Agent package   
* jetsocat,dgw: optimize binary size   

2025.2.3 (2025-07-11) Benoît Cortier <bcortier@devolutions.net>

* dgw: write startup failures into boot.stacktrace file    
  This will make troubleshooting configuration errors much more easier.
* dgw: new TlsVerifyStrict option    
  This adds a TlsVerifyStrict option for controlling the new stricter
  checks on TLS certificates.
  When enabled (true), the client performs additional checks on the
  server certificate, including:
  - Ensuring the presence of the Subject Alternative Name (SAN)
    extension.
  - Verifying that the Extended Key Usage (EKU) extension includes
    serverAuth.
  Certificates that do not meet these requirements are increasingly
  rejected by modern clients (e.g., Chrome, macOS). Therefore, we strongly
  recommend using certificates that comply with these standards.
  The default configuration for fresh installs will include the
  TlsVerifyStrict key set to true.
* dgw,agent: display config file path during initialization   
  Output the full path to the configuration file when initializing the
  configuration for both Devolutions Gateway and Devolutions Agent. This
  simplifies debugging and setup verification.
* dgw: auto-detect proxy setup when performing HTTP requests   
  Look in environment variables to set HTTP, HTTPS or SOCKS proxies.
* agent: auto-detect proxy setup when fetching productinfo.htm    
  Look in environment variables to set HTTP, HTTPS or SOCKS proxies.
* pedm: don't error on profile selection if no assignments   
  If a user has never had a profile assigned, there will be no record of
  them in the user table.
  However, if they try to select a profile, an error is returned. It's
  better to catch this scenario upfront and just return an empty profile
  selection and list.
* webapp: fullscreen handling for ARD web client   
* webapp: fix enter fullscreen button during a running session   
* pedm: add additional context to virtual account code paths   
  Some users are experiencing an error with the virtual account elevator.
  This adds additional context to the virtual account elevator code paths.
* dgw: set default value of TlsVerifyStrict to false   
  Previously, strict TLS verification was performed even when the
  TlsVerifyStrict key was absent from the configuration file.
  From now on, if this key is missing, it will default to
  "TlsVerifyStrict": false.
  This change ensures that existing users who are currently using improper
  certificates will not be affected. At the same time, newly generated
  configuration files will continue to include "TlsVerifyStrict": true by
  default, encouraging using proper certificates from the start.
  New users can still opt out of strict verification by explicitly setting
  the value to false or removing the key entirely if they are willing to
  accept potential compatibility issues with some clients, such as Chrome
  or macOS.
  A warning will be logged if the option is disabled as it may hide latent
  issues.
  Hopefully, this lead the user to enable the option, and fix the
  underlying certificate issue if necessary.
* webapp: fix an issue in the VNC client where display scaling was not correctly
  updated after a server-initiated resize.
* webapp: fix excessive scroll speed in VNC client.
* webapp: fix clipboard monitoring treats clipboard updates from the server as
  local clipboard updates.
* webapp: fix the error when navigator.clipboard.write was called when the
  browser window was not focused.

2025.2.2 (2025-06-27) Benoît Cortier <bcortier@devolutions.net>

* webapp: support dynamic resizing for RDP and VNC sessions   
* webapp: update RDP and VNC web clients   
  - Prevent undesirable scrolling when the canvas is focused.
  - Fix a typo.
  - Fix keyboard input for Firefox.
  - Hide slider in fullscreen mode.
  - Fix a bug in VNC client where ZLIB encoding was not disabled even when
    unchecked from the list.
* webapp: incorrect desktop size when a predefined resolution is selected   
* dgw: [breaking] clean up /jet/net/config route    
  The JSON output of the /jet/net/config route is changed to be more
  convenient in the consumer code.
  Previous output example:
  `
  [
    {
      "name": "vboxnet0",
      "addresses": [
        {
          "V4": {
            "ip": "192.168.56.1",
            "broadcast": "192.168.56.255",
            "netmask": "255.255.255.0"
          }
        },
        {
          "V6": {
            "ip": "fe80::800:27ff:fe00:0",
            "netmask": "ffff:ffff:ffff:ffff::"
          }
        }
      ],
      "mac_addr": "0a:00:27:00:00:00",
      "index": 4
    }
  ]
  `
  New output example:
  `
  {
    "vboxnet0": [
      {
        "family": "IPv4",
        "address": "192.168.56.1",
        "broadcast": "192.168.56.255",
        "netmask": "255.255.255.0",
        "mac": "0a:00:27:00:00:00"
      },
      {
        "family": "IPv6",
        "address": "fe80::800:27ff:fe00:0",
        "netmask": "ffff:ffff:ffff:ffff::",
        "mac": "0a:00:27:00:00:00"
      }
    ]
  }
  `
* webapp: change toolbar activation height   
  When in fullscreen mode, the session toolbar was not appearing
  when the cursor was moved to the top of the screen.
* dgw: [breaking] fail-fast on improper certificate for TLS    
  Certificates missing the auth extended key usage, or missing a subject
  alternative name are now rejected:
  - immediately fail on startup for certificates from filesystem, and
  - fail on certificate resolution for system certificate store.
* dgw: crash when using default port HTTP internal URL    
  The listener task was crashing when the default port for HTTP (80) or HTTPS (443)
  was used in the internal URL of the HTTP listener.

2025.2.1 (2025-06-11) Benoît Cortier <bcortier@devolutions.net>

* webapp: allow dynamically adjust wheelspeedfactor for VNC and ARD sessions  
  The wheel speed factor setting is moved to the toolbar.
* dgw: allow session tokens to be reused in a limited way  
  Add support a configurable reconnection window, allowing token reuse for
  reconnections after disconnection within a defined period. This feature
  will enable more robust handling of temporary disconnections, minimizing
  session disruptions.
  The token can be reused under three conditions:
  - The associated session was not killed.
  - The reconnection window since last disconnection is not exceeded.
  - The number of connections during the reconnection window does not
    exceed 10 (hardcoded value).
  For the last point, this is the maximum number of reconnections allowed
  during the reconnection window. If the reconnection window (e.g.:
  30 seconds) is over while the connection is still alive, the counter
  is reset, and it’s possible to reconnect up to 10 times again. This
  prevents brute force attacks in the situation where the token is stolen,
  although that is tricky to exploit in the first place.
* dgw: support port wildcards for JMUX sessions   
  When the port is set to 0, we do not add a FilteringRule::Port, and
  when the the host is also set to  (i.e.: :0), insert
  FilteringRule::Allow to allow anything.
* dgw: fix terminal recording player CSS issue   

2025.2.0 (2025-06-04) Benoît Cortier <bcortier@devolutions.net>

* webapp: add wheelspeedfactor setting to a VNC and ARD connection forms   
* dgw: emit a warning alert when TLS is not configured and credentials are pushed  
  For instance, proxy-based credentials injection for RDP requires a TLS
  certificate and private key to be configured.
* dgw: proxy-based credential injection for RDP   
* pedm: fix flawed expand_environment function   
* webapp: typo in resolution quality control    
* dgw: [breaking] drop the prxusr, prxpwd, dstusr and dstpwd claims   
  The favored approach when pushing credentials is now to use the
  preflight route.

2025.1.6 (2025-05-23) Benoît Cortier <bcortier@devolutions.net>

* agent: [breaking] Major breaking change in the experimental PEDM module.
  The PEDM module is planned to be released officially in the 2025.2.0 release, but for simplicity we are releasing
  a 2025.1.6 version that will be compatible with RDM 2025.2 so it’s possible for the users to update or install the
  agent before updating the rest of the products to 2025.2.
  If you installed the experimental PEDM module prior to 2025.1.5, you must:
  - Uninstall the current version
  - Run the following PowerShell script as administrator.
  - Install 2025.1.6 or newer.
  `pwsh
  $CurrentUser = "$Env:USERDOMAIN\$Env:USERNAME"
  $Path = "$Env:ProgramData\Devolutions\Agent\pedm"
  if (-Not (Test-Path $Path)) {
      Write-Error "Path does not exist ($Path)"
      exit 1
  }
  Write-Output "Taking ownership of $Path"
  takeown /F "$Path" /R /D Y | Out-Null
  Write-Output "Granting full control to $CurrentUser"
  $Args = ""$Path" /grant:r "$CurrentUser:F`" /T /C"
  Start-Process icacls -ArgumentList $Args -NoNewWindow -Wait
  Write-Output "Deleting $Path"
  Remove-Item -LiteralPath $Path -Recurse -Force
  `

2025.1.5 (2025-05-15) Benoît Cortier <bcortier@devolutions.net>

* dgw: cross-file seeking for recording player    
  Introduces support for seemless playback of multi-files recording playback.
* dgw: preflight API    
  Possible operations:
  - get-version: returns the version of the service.
  - get-agent-version: returns the version of the agent, if available.
  - get-running-session-count: returns the number of active sessions.
  - get-recording-storage-health: returns information about the remaining disk space available for recordings, etc.
  - provision-token: caches the token on the proxy side for later use.
  - provision-credentials: associates a username/password with a token for proxy-side credential injection.
  - resolve-host: DNS resolution of a hostname.
  Possible results:
  - version: the version of the service.
  - agent-version: the version of the side-by-side installed agent, if applicable.
  - running-session-count: the number of running sessions.
  - recording-storage-health: various information regarding recording storage health.
  - resolved-host: the IP addresses resolved for the hostname.
  - ack: acknowledge a given operation was performed with success. 
  - alert: alert message for errors and other information.
* dgw: extend net scanner capabilities   
* dgw: stabilize /jet/net/config   
* webapp: integrate the newer RDP and VNC packages   
  New version of the remote desktop web clients.
  New settings are exposed for VNC, ARD and RDP.
  - VNC-specific settings:  Enabled Encodings (it’s possible to specify
    in a fine-grained manner which codecs are enabled or not),
    Enable/disable cursor pseudo-encoding, etc.
  - ARD-specific settings: Resolutions Quality and Quality Mode settings.
  - RDP-specific: toggle for Unicode mode.
* webapp: option for enabling/disabling display control in RDP web client   
* dgw: improve system store certificate selection    
  The selection is now discriminating based on the extended key usage and
  the not valid before date.
  - Discriminate based on the extended key usage: certificate is ignored
  when the "Server Authentication" (1.3.6.1.5.5.7.3.1) key usage is not
  specified.
  - Discriminate based on the "not valid before" date: certificates not
  yet valid are ignored.
  - Added generous logging to observe the selection process in details.
* installer: resolve potential null reference installing PEDM shell extension   
  The top-level file extension keys may not all exist (in the case of QA,
  HKEYCLASSESROOT\\.ps1 was not present). Although we check for an
  empty default value, we don't check for the presence of the top-level
  key which could cause a null-reference exception and force the installer
  to roll back.
* dgw: properly order system certificates    
  We used the wrong key for sorting the certificates. It should have been
  "validnotafter" instead of "validnotbefore".
* dgw: caching of system store certificates    
  Basic caching is implemented for certificates fetched from the system
  store reducing considerably the number of system calls.
  The lifetime is 45 seconds, so the certificate is still refreshed on a
  regular basis.

2025.1.4 (2025-03-18) Benoît Cortier <bcortier@devolutions.net>

* dgw: add --config-path command-line option    
* dgw: improve debug logs for recording path canonicalization   
  It’s easier to diagnostic why canonicalization failed now.
* dgw: reopen the certificate store for each request    
  When using the system certificate store, we now properly reopen the
  store for each HTTP request, eliminating the need for restarting the
  service when renewing the certificate.

2025.1.3 (2025-03-05) Benoît Cortier <bcortier@devolutions.net>

* agent-installer: don't fail an uninstall if the shell extension can't be unregistered   
  An unexpected error unregistering the PEDM shell extension can cause an
  uninstall to fail; this leads to a bad posture on the user machine.
* dgw: fix a bug where shadowing player was sometimes failing with high frame rate   
* installer: ensure NetworkService has proper file permissions   
  We've had sporadic issues where users cannot update the revocation list
  due to a permissions error on the .jrl file (access denied deleting the
  original file).
  Likely cause:
  - Gateway was installed and created this file(s) at or before version
  2024.1.5
  - In subsequent versions, we switched the service account to
  NetworkService and updated the DACL applied to the top-level
  %programdata%\Devolutions\Gateway directory
  - However, files created previously did not retroactively inherit
  NetworkService's new ACL
  - This doesn't matter for most files where Users has read and execute
  permission
  - Files that need Modify permission won't have it (for example, the
  .jrl and existing log files)
  This version:
  - Updates the SDDL set on the top-level
  %programdata%\Devolutions\Gateway directory to ensure that
  NetworkService can delete subfolders and files
  - Forcibly resets the ACL on files in the program data directory
* dgw: fix WebSocket connection hanging at the end of communication   
  WebSocket close frames were not sent on session termination.
  With this patch, we properly send WebSocket close frames when session terminates.
* dgw: fix missing webapp in deb   
* dgw,agent: target Ubuntu 18.04   
  Properly target ubuntu-18.04, including for the cadeau library which was
  just released with ubuntu-18.04 targeting as well. By targeting
  ubuntu-18.04, we are forward-compatible with ubuntu 20.04, 22.04, 24.04
  but we are also compatible with RHEL8, which uses a version of
  glibc older than ubuntu 20.04.
* dgw: don't use libsql default features   

2025.1.2 (2025-02-20) Benoît Cortier <bcortier@devolutions.net>

* agent-installer: disable restart manager in Agent MSI   
  The restart manager is intended to reduce the number of reboots caused by
  locked files. It attempts to shutdown and relaunch executables that are using
  locked files required by the installer. An interactive prompt is shown to the
  user offering a choice between shutdown/restart of the application (as long as
  the application is integrated with the restart manager) or to reboot.
* dgw: fix an issue where 'Unknown error' was displayed at the end of recording playback   
* dgw: fix an issue where recording ended but the streaming task was not terminated   
* dgw: revert service name to "devolutions-gateway" on Linux   
  The service name was mistakenly renamed to "devolutions-agent" in the previous release.
* agent-installer: prevent invalid configuration due to installer sequencing   
  The PEDM/Session feature toggle was manipulating agent.json after
  InstallFiles.
  The action that initializes agent.json was not actually added to the custom
  actions, and in any case it was sequenced before StartServices (which is
  after InstallFiles).

2025.1.1 (2025-02-05) Benoît Cortier <bcortier@devolutions.net>

* agent: fix downgrade logic for unreleased Devolutions Gateway   
  Fix an updater corner case where the user is trying to downgrade to the
  latest specified version in productinfo.htm while a newer unreleased
  version is installed locally.
* dgw: mute recording player by default to allow autoplay in web browsers   
* agent-installer: add experimental tag to PEDM and session features   

2025.1.0 (2025-01-29) Benoît Cortier <bcortier@devolutions.net>

* dgw: session shadowing               
* dgw: add a replay button on streaming finish   
* jetsocat: (also) return one link per certificate    
  Make jetsocat doctor return one link per certificate in addition to
  the chain link.
* dgw: improve log quality   
  - Enhance the "Peer failure" log to include the peer address and the
  listener kind (in fact, always TCP).
  - Instead of an ERROR-level trace, log an INFO-level trace when the
  wrong protocol is used on the TCP listener.
* dgw,jetsocat: implement WebSocket keep-alive logic   
  Our WebSockets are already responding Pong messages to Ping messages,
  but they were never sending Ping messages.
* dgw: correct typo causing missing packager   
  The control template expects a variable named packager but package was passed.
* dgw: move libxmf.so to /usr/lib   
  This moves libxmf.so from /usr/share/devolutions-gateway to /usr/lib/devolutions-gateway.
  According to the ,
  /usr/share is for architecture-independent data files.
* Add RPM for gateway and agent   
  This commit adds RPM packages for Gateway and Agent to the release
  assets.
  The rpm is generated with fpm, a Linux packaging tool.
  The RPM includes all the assets of the corresponding Debian package,
  including the changelog, copyright, maintainer scripts, and
  webapp/libxmf.so for Gateway.
  Tested with RHEL 9 (glibc 2.34).
* Add changelogs for Linux packaging    
* Remove unused Linux deps   
  This removes unused dependencies.
  libc6 on Debian is glibc on RPM-based systems.
  libc6 version is bumped to 2.31 as that is the version provided by the
  CI runner generating the build.
  libgcc-s1 dependency is removed as it is a dependency of libc6.
  `
  ldd devolutions-gateway
    linux-vdso.so.1 (0x000077b2330a9000)
    libgccs.so.1 =/lib/x8664-linux-gnu/libgcc_s.so.1 (0x000077b22f5b1000)
    libm.so.6 =/lib/x86_64-linux-gnu/libm.so.6 (0x000077b22f4c4000)
    libc.so.6 =/lib/x86_64-linux-gnu/libc.so.6 (0x000077b22f200000)
    /lib64/ld-linux-x86-64.so.2 (0x000077b2330ab000)
  `
  The ldd output for Agent is identical.

2024.3.6 (2024-12-02) Benoît Cortier <bcortier@devolutions.net>

* dgw: persistent job queue for crash resistance   
  This year we added some background tasks in the Gateway that should
  not be canceled, or if they are, should be restarted later. Essentially
  two tasks: mass deletion of recordings (relatively important, but
  it's always possible to launch indexing in DVLS in case of a problem)
  and remuxing recordings to webm format (good to have). If the service
  is killed in the middle of one of these operations, we should resume
  execution on the next startup.
  This persistent job queue is implemented using Turso’s libSQL. Using
  libSQL (or SQLite) for implementing the queue allow us to benefit from
  all the work put into implementing a reliable, secure and performant
  disk-based database instead of attempting to implement our own ad-hoc
  storage and debugging it forever.
* dgw: add agent version field to heartbeat API   
* jetsocat: Schannel diagnostics for Windows    
  These diagnostics will return detailed information about how Windows
  will understand the specified certification chain.
* webapp: session toolbar loading issues   
* webapp: active session connection status in menu    
* dgw: improve logs of rdp extension module   
* dgw: lower the level of the control code log   

2024.3.5 (2024-11-12) Benoît Cortier <bcortier@devolutions.net>

* webapp: the initial 401 error is shown when it should not    

2024.3.4 (2024-11-08) Benoît Cortier <bcortier@devolutions.net>

* jetsocat: make doctor returns links to x509.io   
  Returns a link to x509.io Certificate Viewer in order to inspect the
  certification chain conveniently.
* dgw: shadowing player web-component   
* dgw: /jet/jrec/delete endpoint for mass deletion    
  A new endpoint not taking any parameter via the request path.
  Instead, a list of session IDs is provided in the request body.
* dgw: disallow SCOPE tokens missing the jti claim   
  DVLS generates this claim since its version 2022.1.9.
  This version is almost three years old, and already completely phased
  out, as such it’s more than reasonable to stop supporting this kind
  of token.
* dgw: the recording policy wasn't set for RDP via web   
* dgw: support for .cast files that have two slices with the same timestamp in recording player   
* dgw: allow any header to be set in browser JavaScript HTTP requests   
  We don’t expose any header particularly sensitive from the Devolutions
  Gateway, and the future HTTP bridge will always require a token which
  is only issued on a per-need basis. In fact, in such cases we actually
  want to allow virtually any header to be used for web-based integration
  of various web services (e.g.: VMware dashboard).
  The restriction imposed by the token requirement is strong enough.
* dgw: better custom recording paths handling in heartbeat endpoint    
  On Windows, the std::fs::canonicalize function returns
  Windows NT UNC paths, but our code detecting the mount point does not
  understand that.
  We use dunce to handle that for us instead.

2024.3.3 (2024-10-02) Benoît Cortier <bcortier@devolutions.net>

* pedm: add context menu icon resource   
* agent: devolutions-session bootstrap   
* jetsocat: Windows named pipes and Unix sockets   
* jetsocat: new doctor subcommand for diagnostics   
* pwsh: trace more info when importing Certificate from PFX   
* dgw: set dwShareMode for recording files on Windows   
  On Windows, the default default share_mode set when opening a new file
  is FILESHAREREAD | FILESHAREWRITE | FILESHAREDELETE.
  We now override the sharemode and set it to FILESHARE_READ.
  This makes the recording process more robust by ensuring no other
  process can write or delete the files while the Devolutions Gateway
  is actively writing it.
* jetsocat,dgw: add backpressure in JMUX proxy  
  The memory consumption of the JMUX proxy was unbounded because we used
  an unbounded mpsc channel for message passing.
  Here is a jetsocat-bench.nu run against master:
* dgw: start the recording player immediately when tab is open    

2024.3.2 (2024-08-20) Benoît Cortier <bcortier@devolutions.net>

* agent: initial PEDM implementation  
* dgw: log KDC domain when throwing the error   
  We now print the name of the requested domain when the requested
  domain didn't match the authorized (expected) domain.
* dgw: accept subject name even if it does not match the hostname  
  Configurations where the certificate subject name does not match the
  hostname are now accepted.
  Instead, a few warning and debug log records are added to help
  discover configuration issues in case of problem.
  The problem with the strict approach we had previously is that we
  may reject valid configurations where the hostname was actually
  matched by one of the subject alternative names in the certificate.
* jetsocat: use a larger buffer for plain forwarding   
  By increasing the size of the intermediate buffer from 8k to 16k,
  performance of raw TCP forwarding is increased by ~19.4%.
  Performance was measured using iperf on local network.
* jetsocat,dgw: major throughput improvement for JMUX proxy (Devolutions Gateway Tunnel)           
  See .
* dgw: update cryptography dependencies  
  We keep using ring as our crypto provider for now.

2024.3.1 (2024-08-01) Benoît Cortier <bcortier@devolutions.net>

* dgw: dynamically load XMF native lib on startup   
  The DGATEWAYLIBXMF_PATH environment variable can be used optionally to specify the path to
  the XMF native library.
* dgw: remux webm files when video recording ends   
* dgw: fix recording player parsing problem    
  - Remove usage of btoa, it fails on different charset.
  - Add 1 millisecond if the time of previous event is the same at the next event.
    Otherwise, the player will throw an error.
* webapp: fix RDP connection form - set pre connection blob as not required   
* webapp: add tooltip ellipsis for long netscan service names   
* dgw: [breaking] jet_rec claim is now a string   
  Possible values are:
  - none: No policy to enforce (recording is optional)
  - stream: An external application (e.g.: RDM) must push the
    recording stream via a separate websocket connection
  - proxy: Session must be recorded directly at Devolutions Gateway
    level (not implemented yet)
  Note: Up until now, Devolutions Gateway was rejecting sessions when this claim was found because it couldn’t upheld
  the policy. It’s effectively not breaking anything which wasn’t already broken previously.

2024.3.0 (2024-07-24) Benoît Cortier <bcortier@devolutions.net>

* agent: Devolutions Gateway service updater   
* dgw: add API to trigger Devolutions Gateway update   
* dgw: support .cast terminal recording files   
  The .cast extension is used for "asciicast" files, i.e.: asciinema cast files.
  This is a widely used terminal playback format.
* dgw: preserve DGW access URI base in recording player   
  This is notably important for DVLS side by side setups.
* dgw: fix cast file not working in recording player page   
* dgw: enforce recording policy    
  When recording flag is set and recording stream is closed, the associated
  session is killed within 10 seconds.
* dgw: support for jet_rec claim in JMUX tokens   
* dgw: recording player now scales with the size of the window    

2024.2.3 (2024-06-18) Benoît Cortier <bcortier@devolutions.net>

* installer: fix parsing errors with configuration check  
* installer: package web player  

2024.2.2 (2024-06-18) Benoît Cortier <bcortier@devolutions.net>

* installer: add a basic configuration check   
* dgw: IP restrictions fallback for ngrok TCP listeners    
  Now properly fallbacks to disabling IP restriction rules for TCP
  listeners as well.
* dgw: rework network interface DTO definition    

2024.2.1 (2024-05-22) Benoît Cortier <bcortier@devolutions.net>

* installer: use Win32 to set file permissions   

2024.2.0 (2024-05-21) Benoît Cortier <bcortier@devolutions.net>

* webapp: allow ssh client to use encrypted ssh keys   
* webapp: fix netscan result duplicate and performance improvement   
* webapp: new version button is available even when a more recent version is used   
* webapp: fix misaligned "Fill form" buttons when the hostname is too long   
* webapp: fix force rescan button    
* webapp: add tooltip to menu warning icon when session is closed    
* webapp: prevent suspicious "e" console logs    
  Downgrade the Primeng package as the log was introduced in version 16.5.0.
* webapp: connect session button stays grayed out intermittently    
* dgw: write new JRL into a temporary file, and swap on success    
  It’s preferable to proceed like this to avoid losing current JRL file
  if the file is truncated without being rewritten successfully immediately.
* pwsh: fix reading .pem files from PowerShell runspace   
* webapp: format the error backtrace to show line breaks    
* webapp: menu icon does not update on error for RDP, ARD, VNC    
* webapp: tooltip for the selected protocol is always set to RDP    
* dgw: prevent error traces caused by browser behavior    
  Since those are not actual errors, this was creating noise in the logs.
* dgw: keep HTTP connections open for 10 minutes   
  Most browsers will keep HTTP connections open to increase throughput
  when performing subsequent transactions.
  For simplicity, we don’t distinguish between idle and non-idle
  connections.
* webapp: build using production profile   

2024.1.6 (2024-05-06) Benoît Cortier <bcortier@devolutions.net>

* webapp: add ssh key authentication   
* dgw: add /jet/jrec/play endpoint    
* webapp: network scanning   
* dgw: return disk space available for recordings    
  The total and available space used for storing recordings is now
  returned inside the heartbeat response.
  If the system does not support this operation, the fields are
  excluded from the response.
* dgw: add /jet/jrec/delete/<IDendpoint    
  This new endpoint is used for deleting recordings and allow the
  service provider (e.g.: DVLS) to delete them according to its
  policy.
* dgw: add recordingstorageis_writeable in heartbeat    
* dgw: WebM player for remote desktop recordings    
  Adds a video and xterm player at the GET /jet/jrec/play endpoint which
  supports multiple videos and builds the page dynamically based on the
  type of recording.
* webapp: update IronVNC to 0.2.2    
  - Improve MVS codec performance by about 60%
  - Re-enable MVS codec
* webapp: add analytics   
* dgw: error code on service startup failure    
  Instead of panicking when failing to start the service, we instead
  attempt to log the error to the log file and return an error code.
* webapp: login screen not shown when opening /jet/webapp/client/    
* installer: [breaking] install Gateway service as NetworkService   
* dgw: use a buffer of 1k bytes for ARD VNC sessions    
  Apple ARD uses the so-called MVS video codec.
  It is a tricky codec: Apple didn't implement proper congestion control, so it's basically just TCP controlling the flow (not by much).
  Our MVS implementation for the web client is obviously not as fast as the native one, and can’t keep up when there are too much data in transit.
  To reduce the amount of data in transit, we reduced the size of the copy buffer when using web socket forwarding endpoint and if the application protocol of the session is set to ARD.
* Bump Rust toolchain to 1.77.2   
* Set content type on macOS jetsocat binary   

2024.1.5 (2024-04-04) Benoît Cortier <bcortier@devolutions.net>

* installer: prevent possible prompt for firewall access in Windows installer  

2024.1.4 (2024-03-22) Benoît Cortier <bcortier@devolutions.net>

* installer: add webapp client frontend to .deb package   
* dgw: resolve web frontend on Linux   
* jetsocat: build jetsocat for linux-arm64 target   

2024.1.3 (2024-03-08) Benoît Cortier <bcortier@devolutions.net>

* webapp: version number at the bottom of the app menu   
* webapp: check if a new version is available   
* webapp: bump iron-remote-gui-vnc to 0.2.1   
  - Support for client-side rendered hardware-accelerated cursors
* webapp: improve the error catching for VNC and ARD    
* webapp: update IronVNC to 0.1.6   
  - fix connection not shut down properly
* webapp: shutdown not called when closing from left menu    
* installer: properly write ARP InstallLocation on fresh installs  
* webapp: show error backtrace for VNC, ARD and RDP clients    

2024.1.2 (2024-03-05) Benoît Cortier <bcortier@devolutions.net>

* webapp: authentication list state is not preserved on error    
* webapp: fix web form controls data submission    
* webapp: add favicon   
* webapp: configure angular production build    
* webapp: web form UI - fix spinner for autocomplete   
* webapp: bump IronVNC and IronRDP packages   
  - RDP: fix performance flags
  - VNC: better error status codes on authentication
  - VNC: fix initial screen state not being properly painted
* pwsh: support for non-PEM, binary certificate files    
* webapp: update fontscdn link   

2024.1.1 (2024-02-29) Benoît Cortier <bcortier@devolutions.net>

* webapp: bump IronVNC and IronRDP packages   
  - RDP: enable performance flags
  - VNC: disable MVS codec for ARD
  - VNC: clipboard support
* installer: layout tweaks for better HiDPI support   
* webapp: disable debug logging by default   
  Remove console.logs and turn off debugwasm for IronRDP and IronVNC.
* webapp: UI issues in sidebar menu and web form   
* dgw: fix Linux issues with network scanner   
* webapp: update SSH and Telnet packages   
  Fixes a bug when the hostname is incorrect where the connection to the Gateway was being lost, and close session elegantly.
* pwsh: update PSGallery tags   

2024.1.0 (2024-02-26) Benoît Cortier <bcortier@devolutions.net>

* dgw: standalone web application V1 :tada:
* installer: new Windows installer built using WixSharp
* pwsh: add powershell user management with argon2 password hashing   
* installer: add ngrok configuration support   
* dgw: debug option to set the webapp path   
  The DGATEWAYWEBAPPPATH env variable is conserved.
  A new stable and documented configuration key is added: WebApp.StaticRootPath.
  The environment variable will be checked first, then the key in the config file,
  and if nothing is specified, we fall back to a webapp folder along the executable.
* dgw: network scan HTTP API   
* dgw: use all resolved addresses when connecting    
  This patch ensures Devolutions Gateway does not immediately discard
  resolved addresses which are not emitted first by Tokio’s lookup_host.
  Typically, the first address is enough and there is no need to try
  subsequent ones. Therefore, it is not expected for this change to
  cause any additional latence in the the vast majority of the cases.
  However, just to be on the safe side and enable easier troubleshooting,
  a WARN-level log is emitted when failing at connecting to a resolved
  address. If latence were to be introduced by this patch, we can
  easily be made aware of the problem and investigate further (network
  configuration, etc).
  If this proves to be a problem in the future, we can add filtering
  options. For instance, on a network where IPv4 is not supported or
  disabled, we may want to filter out all the IPv4 addresses which may
  be resolved by the Devolutions Gateway.
* dgw: improve logs quality for JMUX proxy  
  Notably, status codes like ECONNRESET or ECONNABORTED are not
  considered anymore as actual errors, and will be logged accordingly.
* dgw: improve JMUX proxy error display in logs   
* dgw: upgrade Windows store resolve error log   
  This can help with troubleshooting configuration problems with
  Windows system certificate store.
* dgw: better status code for unreachable KDC server   
* dgw: spurious warning when using a wildcard certificate   
* dgw: ensure the hostname matches TLS certificate   
  Warning logs are ignored at this point (logger not yet initialized),
  so it doesn’t really help. Since specifying a hostname not matching the
  TLS subject name is a configuration error, we now return an error upon
  loading the configuration.Log warnings are ignored at this point, so it
  doesn’t really help.
* dgw: better support for ngrok free plan    
  Our installer is allowing the 0.0.0.0/0 CIDR by default because
  premium plans need the IP restrictions to be configured or just
  all external traffic. However this doesn’t play well with the free
  plan. This patch is using a dirty trick to detect the free plan
  and ignores the IP restriction configuration when it is detected.
* dgw: eliminate openssl link dependency on Linux   

2023.3.0 (2023-10-30) Benoît Cortier <bcortier@devolutions.net>

* pwsh: add (Get|Set|Reset)-DGatewayConfigPath cmdlets    
* pwsh: verbosity profile, ngrok tunnel configuration   
* dgw: support for Windows Certificate Store   
  New configuration keys:
  - TlsCertificateSource: Source for the TLS certificate (External or System).
  - TlsCertificateSubjectName: Subject name of the certificate.
  - TlsCertificateStoreName: Name of the System Certificate Store.
  - TlsCertificateStoreLocation: Location of the System Certificate Store.
* pwsh: add new TLS configuration options    
* dgw: support for PFX files    
  PFX files may now be specified in the TlsCertificateFile option.
  Furthermore, a new optional option is added: TlsPrivateKeyPassword.
  This option may be used when the PFX file is encrypted using a passkey.
* dgw: [breaking] adjust ngrok options   
  Some ngrok options are not making much sense for Devolutions Gateway
  and were removed:
  - PROXY protocol: we do not handle PROXY protocol in Devolutions Gateway
    and instead make use of Conn::peer_addr to find the original client IP.
  - Basic Authentication: we have our own way to handle the authentication
    using Json Web Tokens.
  - Schemes: only HTTPS should be used when exposing a Devolutions Gateway
    on internet.
  The Authtoken key was also renamed to AuthToken for readability.
* Update README.md + COOKBOOK.md   

2023.2.4 (2023-10-16) Benoît Cortier <bcortier@devolutions.net>

* dgw: new VerbosityProfile option   
  This adds a stable option to configure log verbosity.
* dgw: add support for more X.509 cert PEM labels   
  Devolutions Gateway will now recognize X509 CERTIFICATE and
  TRUSTED CERTIFICATE as valid PEM labels for X.509 certificates.
* dgw: more trace records for RDP extension   
  This will help when troubleshooting web client issues.
* dgw: improve logs quality     
  - Records additional info on running sessions
  - Improves file rotation
* dgw: proper timeout for HTTP listeners   
* dgw: shutdown streams gracefully after forwarding   
* Update Rust toolchain to 1.73.0   

2023.2.3 (2023-08-15) Benoît Cortier <bcortier@devolutions.net>

* dgw: error 500 when recording folder is missing    
  When listing the recordings, if the recording directory does not exist,
  it means that there is no recording yet (and the folder will be created
  later). However, Devolutions Gateway is attempting to read this folder
  anyway and the HTTP error 500 (Internal Server Error) is returned. This
  patch fixes this by returning an empty list as appropriate.
* dgw: typo in TLS forward route    
  The name of the endpoint was wrong, and thus /jet/fwd/tls was
  returning the 404 Not Found status.
  Furthermore, the with_tls option was not properly set.
* dgw: stabilize RecordingPath and Ngrok options   

2023.2.2 (2023-06-27) Benoît Cortier <bcortier@devolutions.net>

* pwsh: initial devolutions gateway updater tool   
* dgw: durations in seconds in ngrok config 
  Previously, a Duration was deserialized from a string
  using the humantime_serde crate. With this patch, the duration
  is specified in seconds using an integer.
  In other words, this code:
  `rust
  #[serde(default, skipserializingif = "Option::isnone", with = "humantimeserde")]
  pub heartbeat_interval: Option<Duration>,
  `
  Is changed into this:
  `rust
  #[serde(skipserializingif = "Option::is_none")]
  pub heartbeat_interval: Option<u64>,
  `
* dgw: make Ngrok listeners appear in configuration diagnostic 
* dgw: truncated payload after PCB reading    
  Too many bytes are consumed when PCB string is missing the
  null-terminator.
  Indeed, until now the number of bytes to consume was found by computing
  the size of the previously decoded PCB when re-encoded.
  IronRDP will always encode PCB string with a null-terminator (just like
  mstcs client). This is generally correct, but will cause payload
  truncation when the received PCB string did not originally contain
  the null-terminator.
  This patch is changing this. The "cursor API" is used instead, and
  cursor position after reading the PCB can be used to find the number of
  bytes actually read (even if re-encoding the PDU would give a different
  result).

2023.2.1 (2023-06-09) Benoît Cortier <bcortier@devolutions.net>

* jetsocat: JETSOCATLOG instead of RUSTLOG 
* jetsocat / dgw: ignore case for hosts and schemes  
  Case is irrelevant when comparing hostnames and schemes.
  Note: using eqignoreascii_case is okay because we don’t
  really expect unicode in such context.
* dgw: KDC proxy auth using token in path  

2023.2.0 (2023-05-31) Benoît Cortier <bcortier@devolutions.net>

* dgw: /jet/jrec endpoint for session recording          
  Adds new JREC token type for session recording.
  Adds new jet_rft (recording file type) private claim.
  Handles /jet/jrec route for WSS to file streaming.
* dgw: /jet/heartbeat endpoint   
  The /jet/heartbeat endpoint requires a scope token for the
  "gateway.heartbeat.read" scope. It is very similar to /jet/health, but
  returns additional information that should not be publicly available
  such as the current number of running sessions.
* dgw: /jet/jrec/list endpoint   
* dgw: /jet/jrec/pull/{id}/{filename} endpoint    
  Recording files can be fetched using this new endpoint and a
  JREC token with the jet_rop operation set to pull.
* dgw: ngrok tunnel support  
* dgw: add ldap, ldaps application protocols   
* dgw: add known application protocol "tunnel"   
  This is known as Devolutions Gateway Tunnel on RDM side.
* dgw: [breaking] move jet/{tcp,tls} endpoints under /jet/fwd (#407)
  That is:
  - /jet/tcp → /jet/fwd/tcp
  - /jet/tls → /jet/fwd/tls
  This is a breaking change, but these routes were not yet used by any other Devolutions product
  until 2023.2.x releases, so it is safe to change this at this point.
* jetsocat: default port in WebSocket URLs   
  With this change, port may be omitted from the WebSocket URL.
  In such case, the default port will be used (either 80 or 443).
* dgw: log version on start   
  Useful when troubleshooting issues using user’s logs.
* dgw: improve HTTP error reporting   
* pwsh: use .NET 6 RSA APIs when available   
  Use .NET 6 RSA public/private key APIs when available.
* dgw: graceful shutdown  
* dgw: do not enforce scheme in /jet/fwd routes   
  This was inconsistent with other routes such as /jet/jmux where
  dst_hst will have the http or https scheme, but this is
  simply used as a filter policy and Devolutions Gateway will not
  wrap the stream further into an "https protocol layer".
  Instead, we rely on the requested URI to choose between plain TCP
  and TLS wrapping at proxy level (i.e.: /jet/fwd/tcp vs /jet/fwd/tls).
* dgw: re-use TLS client config   
  As of rustls 0.21, it’s possible to disable the TLS resumption that is
  not supported by some services such as CredSSP.
  This allow us to reuse the same TLS client config and connector for
  all proxy-based TLS connections.
  (TlsConnector is just a wrapper around the config providing the
  connect method.)
  Making one of these can be expensive, and should be once per process
  rather than once per connection.
  
* jetsocat: gracefully handle invalid native root certificates
  In tokio-tungstenite crate, the rustls::RootCertStore::add method was used
  to add all the root certificates found by rustlsnativecerts crate.
  This is a problem when an ancient or invalid certificate is present
  in the native root store. rustls documentation says the following:
  This is suitable for a small set of root certificates that
  are expected to parse successfully. For large collections of
  roots (for example from a system store) it is expected that
  some of them might not be valid according to the rules rustls
  implements. As long as a relatively limited number of certificates
  are affected, this should not be a cause for concern. Use
  RootCertStore::addparsablecertificates in order to add as many
  valid roots as possible and to understand how many certificates have
  been diagnosed as malformed.
  It has been updated to use RootCertStore::addparsablecertificates
  instead for maximal compability with system store.
  Parse the given DER-encoded certificates and add all that can be
  parsed in a best-effort fashion.
  >
  This is because large collections of root certificates often include
  ancient or syntactically invalid certificates.

2023.1.3 (2023-03-16) Benoît Cortier <bcortier@devolutions.net>

* installer: fix command execution and add validation   
* dgw: WebSocket-TCP endpoint (/jet/tcp)    
* dgw: WebSocket-TLS endpoint (/jet/tls)    

2023.1.2 (2023-03-13) Benoît Cortier <bcortier@devolutions.net>

* dgw: size-based log rotation    
  Set a maximum size of 3 MB for each file and a maximum of 10 log files.
  With this change, Devolutions Gateway should never consume more than 30 MB for its logs.
* pwsh: sort certification chain from leaf to root    
* installer: improved error handling in Windows installer   
  PowerShell configuration commands are now executed as custom actions instead of WixSilentExec.
  Errors are tracked and, if the installer is running with UI, an appropriate error message is shown to the user.
  PowerShell command output is redirected to a temporary file; in the case of an error we provide the user the path to that file.
  A general command execution error will display a string error value. 
  Custom actions are refactored slightly for consistency and readability:
  - Internal functions now only return void, BOOL, or HRESULT where possible. Errors are always handled as HRESULT and other results (e.g. Win32 error codes, LSTATUS, null references) are converted to HRESULT and handled with the different WiX macros (e.g. ExitOnWin32Error).
  - Consolidate on WixGetProperty instead of MsiGetProperty and be careful to release the resulting strings (ReleaseStr)
  - Consolidate on nullptr instead of NULL
* installer: rollback on error in Windows installer   
  For first time installs, if the installation fails, files that may have been created by the configuration process are cleaned up.

2023.1.1 (2023-02-22) Benoît Cortier <bcortier@devolutions.net>

* dgw: better TLS leaf certificate public key extracting   
  Use x509-cert crate to extract the public key from the leaf
  TLS certificate. x509-cert supports more certificates.
* Update dependencies  
* jetsocat: set execute permission in binary   

2023.1.0 (2023-02-14) Benoît Cortier <bcortier@devolutions.net>

* dgw: clean path PDU extension for RDP  
* installer: show *.cer when browsing for certificate files  
  .cer is another popular extension for certificate files.
* jetsocat: file-based pipes  
  - write-file://<PATH>: write file at the specified location
  - read-file://<PATH>: read wile at the specified location
* dgw: add service version to health check JSON response 
* jetsocat: use rustls-native-certs on macOS and Linux  
  Let rustls use the platform’s native certificate store.
* Update Rust toolchain to 1.67.0 
* jetsocat: enable hardened runtime on macOS  

2022.3.4 (2023-01-16) Benoît Cortier <bcortier@devolutions.net>

* pwsh: nil UUID when creating an empty DGatewayConfig   
  Without this patch, the nil UUID is used as the "missing" value instead of $null.
* installer: ensure default config on install, properly set access URI host  
  Ensures a default config is created using the Devolutions Gateway binary before applying "Configure now".
* installer: avoid Unicode char literals   
  Unicode character literals in source files can be problematic, depending on the editor and encoding.
  Instead, avoid the issue by masking the character with an asterisk instead of a Unicode "bullet".
* Update Rust toolchain to 1.66  
* pwsh: fix links in PowerShell module manifest   
* dgw: add Telnet protocol variant  
  This change is making possible to omit the port in the target host
  field. The Telnet default port will be inferred as appropriate.

2022.3.3 (2022-12-12) Benoît Cortier <bcortier@devolutions.net>

* dgw: set default TCP port to 8181   
* Normalize file extensions   
  By convention:
  - .pem -public key
  - .key -private key
  - .crt -certificate
  Note that this is merely a convention, not a standard, and file openers
  should be able to select a .key file when choosing a public key (through
  the drop-down menu typically)
* installer: start the Gateway service at install time  
* dgw: Accept header parsing in health route   

2022.3.2 (2022-11-25) Benoît Cortier <bcortier@devolutions.net>

* installer: install service as "Local Service" again (fewer permissions) 
* jetsocat: automatically clean old log files  
* dgw: IPv6 support  
* dgw: support for full TLS certificate chain  
* installer: enable configuration of Devolutions Gateway via installer UI on Windows  
* dgw: disable sogar  

2022.3.1 (2022-10-03) Benoît Cortier <bcortier@devolutions.net>

* dgw: improve CLI output  
* dgw: extend subkey capabilities to KDC tokens  
  With this change, a subkey is allowed to sign a short-lived KDC token.

2022.3.0 (2022-09-21) Benoît Cortier <bcortier@devolutions.net>

* dgw: revert service as "Local Service"  
* dgw: Content-Type header present twice for Json responses   
  Indeed, Content-Type is a "singleton field": a single member is anticipated as the field value.
  RFC9110 says:
  Although Content-Type is defined as a singleton field,
  it is sometimes incorrectly generated multiple times,
  resulting in a combined field value that appears to be a list.
  Recipients often attempt to handle this error by using
  the last syntactically valid member of the list, leading to
  potential interoperability and security issues if different
  implementations have different error handling behaviors.
* jmux-proxy: properly cancel proxy task   
  Previously, JMUX proxy task wasn't properly shut down because tokio
  tasks are detached by default (similar to std::thread::spawn). This
  adds a helper wrapper to explicitely specify whether a task should be
  joined or detached.
* OpenAPI document and auto-generated C# and TypeScript clients
* dgw: retrieve KDC token from the path  
* dgw: subkey tokens   
* dgw: support for CORS calls   
* dgw: expose gateway ID in configuration endpoint  
* dgw: add general claim jetgwid   
  When this claim is specified, a given token can only be used on a Gateway with the very same ID.
* dgw: wildcard scope tokens   
* dgw: config pushing endpoint  
* dgw: lossless and simpler config DTO  
* dgw: subscriber API  
* dgw: add --config-init-only cli option  
* dgw: limit JMUX wildcard addresses   
  The same port must be used.
* dgw: jet/health endpoint now returns Gateway identity
  The Accept HTTP header must be set to application/json for this.
* powershell: update module  
  - Deprecate PrivateKeyFile and CertificateFile in favor of
  TlsPrivateKeyFile and TlsCertificateFile.  This change is backward
  compatible (older naming are recognized by cmdlets).
  - Add Id, Subscriber and SubProvisionerPublicKey to config class.
  - Allow Set-DGatewayConfig to set Id, Subscriber and
  SubProvisionerPublicKey values.
* dgw: forced session termination support  
  This adds the endpoint POST /jet/session/<id>/terminate.
  This is similar to what we had back in Wayk Bastion except it’s not P2P.
* dgw: maximum session lifetime enforcing  
  This adds a new claim jet_ttl specifying the maximum lifetime for a
  given session. Devolutions Gateway will kill the session if it is still
  running after the deadline.
* jetsocat: HTTP proxy listener  
  HTTP proxy listener now handles both HTTPS (tunneling) proxy requests
  and HTTP (regular forwarding).
* dgw: Smaller token reuse interval for RDP sessions  
  With this change, we do not allow reuse for RDP sessions more than a few
  seconds following the previous use. The interval is 10 seconds which is
  expected to give plenty of time to RDP handshake and negotiations. Once
  this interval is exceeded, we consider the RDP session is fully started
  and the same token can't be reused anymore.
  Two reasons why this is beneficial:
  - Security wise: the reuse interval is considerably shortened
  - Feature wise: more efficient forced RDP session termination
  Regarding the second point: Windows’ mstsc will keep alive the session
  by re-opening it immediately. Because we allow token reuse in a limited
  fashion for RDP, as long as the association token is not expired,
  the terminate action has effectively no visible effect (besides that
  multiple sessions occurred). Reducing the reuse interval greatly
  improves the situation.

2022.2.2 (2022-06-14) Benoît Cortier <bcortier@devolutions.net>

* Update dependencies with CVE reports
* pwsh: update token generation cmdlet
* dgw: remove unused /jet/sessions/count route
* dgw: lossless unknown application strings
  With this change, unknown application protocols will display session information as well.
  Previously, any unknown value was just treated as the "unknown" string.

2022.2.1 (2022-05-30) Benoît Cortier <bcortier@devolutions.net>

* Migrate logging infrastructure to tracing
* dgw: duplicate /jmux and /KdcProxy endpoints under /jet
* dgw: log files are now rotated on a daily basis (old log files are deleted automatically)
* dgw: new LogDirective config option
* dgw: downgrade health route logs to debug level
* dgw: JMUX filtering through claims (* is used to generate an "allow all" rule)
* dgw: optional application protocol claim in JMUX tokens to find good default ports
* dgw: PowerShell via SSH application protocol has been renamed from pwsh to ssh-pwsh
* dgw: new known application protocols
  - PowerShell via WinRM (winrm-http-pwsh, winrm-https-pwsh)
  - VNC (vnc)
  - SCP (scp)
  - HTTP (http)
  - HTTPS (https)
* jetsocat: process watcher option (--watch-parent, --watch-process)
* jetsocat: pipe timeout option (--pipe-timeout)
* jetsocat: HTTP(S) tunneling (proxy) listener for JMUX proxy (http-listen://<BINDING_ADDRESS>)

2022.1.1 (2022-03-09) Benoît Cortier <bcortier@devolutions.net>

* diagnostics/configuration endpoint now also returns Gateway's version
* New diagnostics/clock endpoint to troubleshoot clock drift
* Initial KDC proxy implementation
* Windows installer (MSI) now installs Gateway service as "Local Service" (fewer permissions)

2021.1.7 (2021-12-07) Benoît Cortier <bcortier@devolutions.net>

* JMUX multiplexing protocol implementation for jetsocat and gateway server
* Improve various startup validations and diagnostics
* Support for generic plain TCP forwarding (e.g.: raw SSH forwarding)
  This requires sending a preconnection PDU containing an appropriate token
* Duplicate root HTTP endpoints under /jet (this help simplifying routing configurations)
* Support for alternative hosts to try in successive order
* Token reuse mitigation based on IP address (RDP protocol requires to connect multiple times
  and previously used token can't just be rejected)

2021.1.6 (2021-08-11) Benoît Cortier <bcortier@devolutions.net>

* jetsocat now builds for Apple Silicon (aarch64-apple-darwin)
* Update SOGAR and replace sogar-cli with sogar-core
* Authorization improvements (PR#174, PR#175)
* Add an endpoint to retrieve logs (GET /diagnostics/logs)
* Add an endpoint to retrieve configuration (GET /diagnostics/configuration)
* Add an endpoint to list sessions (GET /sessions)

2021.1.5 (2021-06-22) Benoît Cortier <bcortier@devolutions.net>

* jetsocat tool has been rewritten and CLI overhauled
* SOGAR registry support
  - Recorded sessions can be pushed to a registry
  - Devolutions Gateway itself can be used as a registry

2021.1.4 (2021-05-04) Benoît Cortier <bcortier@devolutions.net>

* Add logs to track all HTTP requests received and processed
* Add Linux service registration support in debian package
* Add Install/Uninstall package commands in PowerShell module

2021.1.3 (2021-04-13) Benoît Cortier <bcortier@devolutions.net>

* Fix infinite loop issue when the precondition pdu was not completely received
* Fix possible stability issue with protocol peeking

2021.1.2 (2021-03-26) Benoît Cortier <bcortier@devolutions.net>

* Fix broken Linux container image (missing executable)
* Add PowerShell module .zip/.nupkg to release artifacts
* Add experimental session recording plugin architecture

2021.1.1 (2021-02-19) Benoît Cortier <bcortier@devolutions.net>

* Fix missing internal version number update

2021.1.0 (2021-02-19) Benoît Cortier <bcortier@devolutions.net>

* Internal upgrade from futures 0.1 to 0.3
* TCP listener now routes both RDP and JET
* Remove unneeded dummy HTTP listener

2020.3.1 (2020-12-03) Benoît Cortier <bcortier@devolutions.net>

* Fix IIS ARR websocket issue (SECWEBSOCKETPROTOCOL header)
* Update Devolutions Gateway to internal version 0.14.0

2020.3.0 (2020-10-27) Benoît Cortier <bcortier@devolutions.net>

* Initial PowerShell module public release
* Update Devolutions Gateway to internal version 0.14.0
* Support file to configure the Devolutions-Gateway (gateway.json)
* Update CLI parameters to match parameters defined in file
* WAYK-2211: candidate gathering jet token restriction

0.12.0 (2020-08-25) Benoît Cortier <bcortier@devolutions.net>

* Add Jet V3 connection test support
* Add /jet/health route alias for /health (for simplified reverse proxy rules)

0.11.0 (2020-05-28) Benoît Cortier <bcortier@devolutions.net>

* Fix websocket connection. Enable HTTP upgrade for the hyper connection.
* Add jet instance name in health response.

0.10.9 (2020-05-13) Benoît Cortier <bcortier@devolutions.net>

* Fix websocket listener. An error was returned by the tls acceptor. Ignore those errors.

0.10.8 (2020-05-12) Benoît Cortier <bcortier@devolutions.net>

* Don't panic if listeners future returns an error. Just print the error and close the application

0.10.7 (2020-05-12) Benoît Cortier <bcortier@devolutions.net>

* Exactly same as 0.10.6 (forced re-deployment)

0.10.6 (2020-05-12) Benoît Cortier <bcortier@devolutions.net>

* Exactly same as 0.10.5 (forced re-deployment)

0.10.5 (2020-05-11) Benoît Cortier <bcortier@devolutions.net>

* Exactly same as 0.10.4 (forced re-deployment)

0.10.4 (2020-05-11) Benoît Cortier <bcortier@devolutions.net>

* Add module name in logs.
* Add curl to Docker container.

0.10.3 (2020-05-08) Benoît Cortier <bcortier@devolutions.net>

* Exactly same as 0.10.2 (forced re-deployment)

0.10.2 (2020-05-05) Benoît Cortier <bcortier@devolutions.net>

* Remove color from logs

0.10.1 (2020-03-26) Benoît Cortier <bcortier@devolutions.net>

* Exactly same as 0.10.0 (workaround to deploy a new version in prod without issue with ACI)

0.10.0 (2020-03-23) Benoît Cortier <bcortier@devolutions.net>

* Add provisioner public key
* DVC with GFX integration
* Fixes an issue where some associations were not removed (ghost associations).
