Selecting a token no longer copies it. Clicking a row, or just arrowing past one, used to copy the code and, for HOTP, burn a counter, so scrolling through the list could silently desynchronise an account from its provider. Selection is now inert and each row carries an explicit Copy or Generate button, with Enter and Ctrl+C as the keyboard equivalent. Underneath that, HOTP counters are written to the encrypted database before a code is ever shown, in a single transaction, which also means the GUI and the command line finally agree on what the stored counter means. The tray menu was separately empty on every desktop except KDE Plasma, and had been since the tray was rewritten: right-clicking the icon opened a blank rectangle on GNOME, Cinnamon, MATE, Xfce and Waybar alike. That is fixed too, and OTPClient can now start minimized to the tray and start at login. Alongside all of those: the clipboard is no longer wiped out from under another application, locking clears the dialogs it used to leave open, imports say which entries they skipped and why, backup reminders are tracked per database instead of globally, and a round of fixes lands for things that never worked inside the Flatpak sandbox. A pre-release audit of the whole release then turned up a handful more that had never worked anywhere: GNOME Shell search results that did nothing when activated, desktop integration that could not be started at all on sessions using dbus-daemon, and exports that reported success after writing nothing.
- FIX: merely selecting an HOTP token consumed its counter. Single-click and arrow-key navigation both went through the copy path, so browsing the list advanced counters with nothing to show for it, and enough of that would desynchronise the account from its provider. Selection now does nothing but select. A new Action column carries a button per row, copy for TOTP and generate for HOTP, labelled by its icon and its tooltip; the same action heads the row's right-click menu, a double-click on the row does the same, Enter and Ctrl+C activate the selected token while the list has focus, and Enter also activates a search result
- FIX: the validity countdown was drawn only for the selected row, a leftover from when selecting a row was what revealed its code. With selection inert the two came apart, and a code could sit visible with no countdown beside it, most obviously right after the row's own Action button revealed one: the button claims the click, so the row never gets selected. The countdown now follows the code it counts down and appears for every TOTP that is showing one. HOTP rows no longer get one at all, having no rotation period to count down
- FIX: toggling "Hide OTPs by Default" left the already-drawn rows alone until a scroll or a selection change rebound them. The refresh was wired up in the window's constructed(), which reads the application property before GObject has set it, so the hook was never connected at all
- FIX: an HOTP counter could be shown or copied without ever reaching disk. The GUI generated the code, advanced the counter in memory, and deferred the encrypted re-save by up to five seconds to coalesce bursts of clicks; a crash, a kill, or a power loss inside that window handed out a code the database no longer knew it had issued. Generation and persistence are now one atomic transaction, and the code is not revealed until the write has committed
- NOTE: the stored HOTP counter now means the next unused code in both interfaces. Older GUI versions stored the last generated one while the CLI stored the next, and there is no way to tell which wrote a given value, so existing counters are left exactly as they are. If an HOTP account rejects its first code after upgrading, generate the next one or resynchronise the counter with the provider. This affects HOTP only, and only accounts previously used from the GUI
- FIX: a database still in the version 1 or 2 format could crash the app while being upgraded. If the decryption that follows the upgrade failed, after a rekey with the wrong password, on a truncated file, or with the secure-memory pool exhausted, the same buffer was released twice. Upgrading is the first thing an older database does on this release, so the window was narrow but badly placed
- FIX: a database whose directory is full, read-only or over quota could not be saved at all. The lock file added in 5.1.x reported "Failed to open database lock" and stopped there, where it was meant to warn once and carry on unlocked, which is what earlier releases did. Sandboxed builds were the most exposed, the lock sitting beside the database inside the Flatpak's own data directory
- FIX: the backup taken beside the database was overwritten with a copy of the database that had just been saved, so it held the same generation as the file it was there to protect and could not be used to go back. It is now taken before the write and left alone afterwards, and failing to write it no longer aborts the save
- FIX: exiting or locking wiped the clipboard even when the user had since copied something else, destroying unrelated data. OTPClient now clears the clipboard only while it still owns the content it put there, and copying anything elsewhere cancels both the pending wipe and the automatic next-code copy
- FIX: locking left sensitive dialogs open with their contents intact. A displayed QR code, a typed secret, an export password, or an unlock prompt survived the lock in memory and on screen. Locking now closes those dialogs, zeroes their entry buffers, drops their QR textures and snapshots, and cancels any operation still in flight, including when an open file chooser is holding the dialog alive
- FIX: a new encrypted migration export could be created with an empty password, producing a file that looked encrypted and was not. Encrypted exports now require a password. Existing empty-password exports still import, so nothing already on disk becomes unreadable
- FIX: encrypted Aegis, Authenticator Pro and 2FAS exports were written from a buffer sized with different formatting flags than the dump that filled it, and the size mismatch was checked against a value the function cannot return
- NEW: partial imports now report what was skipped and why, per entry, instead of silently importing fewer tokens than the file contained. The command line keeps a success status when at least one valid entry was imported and prints the warnings to stderr; input with nothing valid in it fails and leaves the database untouched
- FIX: malformed third-party backups could slip past the importers. The Aegis, Authenticator Pro and 2FAS readers now check that the entry list is actually a list, validate and repair each token before accepting it, report a parse failure through an error instead of a printed line, and no longer leak the fields of an entry they reject
- FIX: an export that could not be written reported success. None of the four exporters closed the file they had opened, and with the atomic-replace mode in use the rename happens inside that close, so a full disk or an exceeded quota produced "Data successfully exported to" over a truncated file, with a stray temporary left beside it. This is the backup feature, so the silence was the worst part of it
- FIX: a token whose account name contains a percent sign, or whose issuer contains a colon, did not survive a round trip through our own plain-text export. The label was percent-decoded twice, so "alice 100%" was rejected outright on re-import and "Acme:Corp" was split in the wrong place. Query values were decoded twice as well, which dropped any token with an issuer such as "50%off". Exports now escape the two halves of the label separately and imports decode exactly once. Files written by older releases still import
- FIX: importing a large file of junk produced one diagnostic line per skipped entry and handed the lot to a single label, which for a big enough file meant hundreds of megabytes of text nobody could read. The list now stops at the first fifty and counts the rest
- FIX: reading an otpauth file trusted the size reported before the read rather than the number of bytes actually read, so a file rewritten shorter in between was read past its end and then zeroed past its end
- FIX: secrets were left in ordinary, pageable memory in three places: the key that unwraps an encrypted Aegis backup, the per-token seeds handed back by the Google Authenticator migration decoder, and the URI written by the FreeOTP+ exporter. All three now use the secure pool or are wiped before being released
- FIX: Steam tokens were exported with the issuer named twice, which strict third-party parsers reject
- FIX: the command line's JSON output was not a single document and its CSV had no header row, so neither could be piped into an ordinary parser. Diagnostics also went to stdout, mixed in with the data. JSON is now one document, CSV starts with a header, and diagnostics go to stderr
- FIX: the command line never saved the master password to the keyring on first run, so with Secret Service enabled it asked for the password on every single invocation and never explained why. The store was started asynchronously in a process that has no main loop to finish it
- FIX: every argument-validation error from the command line went to standard output, mixed in with the data, contrary to what the manual page promises. A mistyped option fed an English sentence to whatever was parsing the JSON, and redirecting stdout to /dev/null threw away the only diagnostic there was. They now go to standard error
- FIX: the backup reminder tracked one global timestamp, which could not say which database it referred to and was also bumped by migration exports, so exporting for another app suppressed a genuine reminder. Backup history and snoozes are now recorded per database, and exports no longer count as backups from either interface. The old global value cannot be attributed to a database, so it is not carried over: after upgrading, each database reads "No backup recorded" until you take one, and any active snooze is reset
- FIX: search-provider settings needed a restart, typically a logout, to take effect. Disabling the provider, clearing its keyword, or turning off Secret Service now applies immediately and revokes cached keys, cached entry lists, and any activation ID already handed out. A clipboard delivery in flight when the settings change can no longer land afterwards
- FIX: an HOTP search result from a database other than the open one had nowhere to write its counter. Activating one now opens the owning database so it can be unlocked and generated there, rather than appearing to work
- FIX: drag-reordering the list when the save failed left what is on screen and what is in the database disagreeing about which row is which. The next Copy or Generate then acted on a different account, and for HOTP that meant advancing and storing another token's counter. The list is now rebuilt from the database whenever a reorder fails to commit
- FIX: importing or exporting settings from a network or phone mount, sftp, SMB, MTP or a cloud drive, crashed the app. Those locations have no local path, and the failure was reported by reading an error that had never been set. The unsupported location is now named instead. Exporting a backup to one of them also claimed to have succeeded without writing anything
- FIX: searching while the database was locked froze the window for minutes and filled the journal with warnings. The group list is empty while locked, and the loop over it counted down from an empty list rather than skipping it
- FIX: clicking another database in the sidebar while the current one was locked switched to it anyway, out from under the lock
- FIX: a QR code pasted from the clipboard with a transparent background never scanned. Pasted images arrive with their colour channels premultiplied by alpha, which the brightness calculation ignored, so a transparent background read as solid black. Images opened from a file were never affected
- FIX: the typed Base32 secret and the export password were left sitting in their entry buffers when the dialog closed along certain paths, instead of being zeroed
- FIX: several memory leaks in the GUI, and one path where a dialog could be disposed twice
- FIX: pressing Enter on a GNOME Shell search result did nothing at all, and never had. A malformed format string meant the handler read none of its arguments, so there was no copy, no notification and no error, only a warning in the journal. Results appeared and were drawn correctly, which is what made the feature look like it worked
- FIX: neither the search provider nor the KRunner plugin could be started at all on sessions that activate services through dbus-daemon rather than systemd, which covers the Debian and Ubuntu defaults, distributions without systemd, and anything run under dbus-run-session. The service files named the executable without a path, and dbus-daemon does not search PATH. The Flatpak was never affected
- FIX: with the search provider disabled, the process exited before taking its bus name, so every search produced a spawn error for GNOME Shell and KRunner instead of an empty result. It now answers, with nothing to show, and starts serving again the moment the feature is re-enabled
- FIX: a locked login keyring froze the search provider inside the first search it was asked for, and each database it then had to decrypt blocked it again, with every other request queued behind. The keyring lookup and the key derivation now run off the main loop
- FIX: activating a search result whose password is not in the keyring, or whose database will not decrypt, did nothing whatsoever, not even a log line. The reason is now reported
- FIX: handing the code to a clipboard tool could hang the search provider indefinitely if the tool never returned, which is what an xclip against an unreachable display does. The call is now asynchronous and bounded by a timeout
- FIX: the notification carrying the code is now marked transient, so desktops keep it out of their notification history
- NOTE: the search provider's trigger keyword is a query filter, not an authentication mechanism, and is no longer described as one. Desktop search additionally requires Secret Service access, a saved database password, and the provider to be enabled
- FIX: the tray menu was an empty rectangle on every host built on libdbusmenu, which is GNOME with AppIndicator, Cinnamon, MATE, Xfce, Ayatana and Waybar. The tray declared dbusmenu version 3, which makes clients fetch labels with GetGroupProperties and dispatch clicks through EventGroup, and neither method existed, so both menu entries were silently dropped. The group methods are now implemented, and clicking an entry works rather than doing nothing (#470, Flathub #81)
- NEW: start minimized to the tray, from Settings under Integration or with
otpclient --start-minimized. It needs minimize-to-tray and a real system tray, and is ignored with the window shown normally when either is missing. The database is deliberately left locked, so the first time you bring the window up it asks for the password (#471)
- NEW: start at login, from Settings under Integration. Native builds write an autostart entry; the Flatpak asks the desktop through the background portal, which a few desktops do not implement, and there the setting is greyed out. The entry follows the start-minimized preference
- FIX: an autostart entry created by hand, or by GNOME Tweaks' Startup Applications, was deleted on the first launch of this release. The start-at-login setting is new and defaults to off, and startup enforced that against a file it had never written. An entry already present is now adopted, with the setting turned on to match, instead of being removed
- FIX: with start-minimized on, the first click on the tray icon always asked for the master password, even with the system keyring enabled and the password saved there. The deferred unlock never consulted the keyring; it does now, which is the combination start-at-login exists for
- FIX: the start-at-login and background-permission settings recorded what had been asked for rather than what the desktop agreed to. A refusal, a timeout, or a quit part way through left a switch claiming a state that was not real, the worst shape of that being a login entry nobody can see still launching the app while the switch reads off. Every answer is now reconciled against what the desktop actually said, an inconclusive one is remembered and retried on the next launch, and only one background request is ever in flight
- FIX: the autostart entry named the executable without a path and carried no TryExec, so an install outside the session's PATH wrote an entry that silently never launched, and uninstalling left one that failed at every login. It now carries the absolute path it was installed to
- FIX: the background-permission prompt was closed out from under the user after a minute, which turned minimize-to-tray off and blamed the desktop for refusing it. The wait is now five minutes, and a local failure to write the autostart file no longer reports itself as a refusal from the desktop either
- FIX: a tray host restarting, a GNOME Shell reload or a plasmashell --replace, force-raised a window the user had hidden, and on a start-minimized launch it brought the password prompt up with it. A short grace period now tells a panel that is coming back from one that is gone
- FIX: webcam QR scanning has never worked in the GTK4 rewrite, on any platform. The scanner opened a zbar preview window instead of the camera, then failed on every frame and reported a timeout. It now opens the camera, and no longer needs an X display to do it
- FIX: in the Flatpak, activating a search result copied nothing. The daemon shells out to a clipboard tool and the runtime shipped none, so every candidate failed silently. The tools are now bundled, the Wayland session is detected from WAYLAND_DISPLAY rather than a variable the sandbox may not set, every available tool is tried instead of committing to one, and a failure is reported instead of being swallowed
- FIX:
otpclient-cli failed with "Application does not handle command line arguments" whenever the GUI was running, because both registered the same application id and the CLI became a remote of the GUI. This mattered rarely before and would have become permanent with start-at-login
- FIX: databases opened from outside the Flatpak's own data directory were saved without any lock held. The document portal implements POSIX record locks and refuses flock outright, which is what the code used, so the "Database lock not supported on this filesystem" warning was reached on every save. Locking works again for those databases
- FIX: a database picked from outside the sandbox could stop opening after a reboot, on btrfs and other filesystems whose device numbers are not stable, and the dialog then suggested two things that could not recover it. The dialog now says the sandbox lost access rather than that the file is missing, and offers to re-pick it
- FIX: "Locate..." on the "Database No Longer Accessible" dialog routed into the plain open picker, which appends a row, so relocating a database left the old entry behind and the new one under a different name. It now replaces the path on the row that is already there, keeps its name, drops the duplicate if the target was listed twice, and moves the saved Secret Service password across to the new path
- FIX: a settings backup silently dropped the search-provider keyword and the clipboard-clear timeout, both of which the settings dialog offers, and an imported sidebar-visibility value did not reach a window that was already open
- FIX: turning minimize-to-tray off inside the Flatpak left a dead icon in the panel until the app exited, because the sandboxed tray had no bus name it could release
- FIX: the tray icon now says so when the database is locked, and the "Show OTPClient" entry raises the window on Wayland instead of being blocked by focus-stealing prevention
- FIX: every Flatpak launch logged a warning about not being able to subscribe to suspend events. The system bus is not there to be reached, so the attempt is no longer made and no longer complained about. Locking on screen lock is unaffected
- NOTE: the search provider is a separate process with its own lock state. A hidden or locked GUI does not stop search from working, and using search does not unlock or reveal the GUI
- NOTE: if you use the system keyring to unlock automatically and turn start-minimized on, OTPClient will sit in the tray over a locked database rather than an open one. That is intentional, and it is the reason the first show asks for the password