### RDP NTLM default
New [rdp] config section with default_auth_pkg. The resolver in
session.rs walks entry value -> config default -> hardcoded "ntlm".
Kerberos/Negotiate are still selectable per-entry or via the config
override, but the default is NTLM because Kerberos needs a KDC
reachable via DNS (often over TCP) and its failure mode is a silent
RDP hang that looks exactly like an unrelated network issue.
Existing entries and Guacamole-imported entries that stored
auth_pkg = None now resolve to NTLM automatically. Admins who do
run Kerberos-integrated hosts can set default_auth_pkg =
"kerberos" or "negotiate" in config.toml to restore the old
behaviour.
UI: the entry modal's NLA dropdown now says "Server default (NTLM)"
instead of "Default (negotiate)" so the behaviour matches the
label. Added an explicit "Negotiate (Kerberos first, NTLM fallback)"
option for completeness.
5 unit tests cover the resolver matrix (entry wins, empty entry
falls through, no entry falls through, empty config default falls
through, server default wins when entry is None).
### Connections tree persistence
Folder expansion state and the selected folder are now persisted
to localStorage, so reopening the page / logging back in no longer
collapses the whole tree or snaps you back to the alphabetical
first folder.
- `rustguac_connections_expanded`: {scope|path: true} map, saved
on every toggleFolder() and on the auto-expand-on-subfolder-
create path.
- `rustguac_connections_selected`: {scope, path}, saved on every
selectedFolder assignment (click, new folder, new subfolder,
delete-to-null, move entry).
On page load, loadFolders() now chains: fetch top-level folders ->
restoreExpandedTree() walks saved keys shallowest-first so deeper
paths can resolve via findFolder() after their ancestors populate
subfolderCache -> try restoring saved selection -> fall back to
the current auto-select-first behaviour only if nothing restored.
Stale keys (deleted folders, ACL-revoked folders) are dropped
opportunistically during the restore walk. Per-browser, not
per-user; try/catch wraps every storage call so private-mode / quota
errors degrade silently to the pre-persistence behaviour.
- Switch default theme from dark to aurora across server config,
all 9 static HTML pages, example config, and docs
- Fix theme docs: list all 8 presets (was 6, missing jaguar/aurora),
add missing type_vdi_bg/type_vdi_fg fields
- Add Vault/address book setup as recommended post-install step in
installation docs — the address book is the primary user-facing
feature and requires Vault
- Renumber subsequent install steps
- Add max_sessions (default 500) and max_sessions_per_user (default 50)
config options. Session creation is rejected with a clear error when
limits are reached. Set to 0 for unlimited (backward compatible).
- Add background reaper that removes completed/error/expired sessions
from the in-memory HashMap after session_cleanup_delay_secs (default
300s). Session history in SQLite is not affected.
- Prevents resource exhaustion from unbounded session creation and
memory leak from accumulated completed sessions.
Closes#99
Switch reqwest from rustls-tls-webpki-roots to rustls-tls-native-roots
so the OS trust store is used by default — private CAs installed
system-wide now work without extra config.
Add ca_cert and tls_skip_verify options to [oidc] for environments
where the system store isn't available or for debugging TLS issues.
Improve OIDC discovery error formatting to surface the actual cause
(issuer mismatch, TLS failure, etc.) instead of opaque "Request failed".
Closes#94
RemoteApp/RAIL (closes#19):
- Pass remote-app, remote-app-dir, remote-app-args through to guacd
- Address book UI: collapsible RemoteApp section for RDP entries
Recording rotation:
- New [recording] config section (backwards-compatible with recording_path)
- Automatic disk-space management: max_disk_percent, max_recordings thresholds
- Background rotation task with configurable interval
- Sidecar .meta JSON files track address book entry per recording
Per-entry recording overrides:
- Address book entries can enable/disable recording and set max recordings
- Per-entry rotation runs on session disconnect
- UI: collapsible Recording Settings section for all connection types
Bump version to 0.4.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Vault TLS: replace hardcoded danger_accept_invalid_certs(true) with
configurable tls_skip_verify option (default: false)
- Share tokens: use constant-time SHA-256 hash comparison to prevent
timing side-channel attacks
- OIDC pending states: add 10-minute TTL, evict stale entries on each
login to prevent unbounded HashMap growth
- Recording path traversal: add canonical path validation as defense-
in-depth alongside existing string checks
- Frontend XSS: escape all user-controlled data (filenames, paths) in
innerHTML via escapeHtml/escapeAttr in client.html and recordings.html
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>