⇦ | otpclient [main]
Last updated on: 2026-10-07 20:18 [UTC]

Metadata for otpclient in main

com.github.paolostivanin.OTPClient.desktop - 5.2.0-1 ⚙ amd64 ⚙ arm64 ⚙ armhf ⚙ i386 ⚙ loong64 ⚙ ppc64el ⚙ riscv64 ⚙ s390x

Icon
---
Type: desktop-application
ID: com.github.paolostivanin.OTPClient.desktop
Package: otpclient
ProjectLicense: GPL-3.0+
Name:
  C: OTPClient
Summary:
  C: Application for managing TOTP/HOTP tokens with built-in encryption
Description:
  C: |-
    <p>OTPClient is a secure and easy-to-use desktop client for TOTP and HOTP one-time passwords, built with
    GTK4 and libadwaita. Features:</p>
    <ul>
      <li>multiple databases with sidebar management and cross-database search</li>
      <li>token grouping with quick filtering</li>
      <li>desktop search provider for GNOME Shell and KDE KRunner (opt-in trigger keyword)</li>
      <li>command-line companion (otpclient-cli) with scriptable table/JSON/CSV output</li>
      <li>support for TOTP, HOTP, and Steam codes</li>
      <li>configurable digits (4 to 10), period (1 to 120 seconds), and algorithm (SHA1, SHA256, SHA512)</li>
      <li>import and export of encrypted/plain Aegis backups</li>
      <li>import and export of encrypted/plain Authenticator Pro and 2FAS backups</li>
      <li>import and export of plain FreeOTP+ backups (key URI format)</li>
      <li>import of Google Authenticator migration QR codes (file, webcam, clipboard)</li>
      <li>integration with the OS secret service provider via libsecret (opt-in)</li>
      <li>local database encrypted with AES-256-GCM and Argon2id key derivation; plaintext lives only in
      libgcrypt secure memory while unlocked</li>
    </ul>
Developer:
  id: com.paolostivanin
  name:
    C: Paolo Stivanin
Categories:
- System
- Security
Keywords:
  C:
  - otp
  - totp
  - hotp
  - "2fa"
  - "2factor"
  - "2fa-client"
  - "2step"
  - twostep
Url:
  homepage: https://github.com/paolostivanin/OTPClient
  bugtracker: https://github.com/paolostivanin/OTPClient/issues
Icon:
  cached:
  - name: otpclient_com.github.paolostivanin.OTPClient.jxl
    width: 48
    height: 48
  - name: otpclient_com.github.paolostivanin.OTPClient.jxl
    width: 64
    height: 64
  - name: otpclient_com.github.paolostivanin.OTPClient.jxl
    width: 128
    height: 128
  remote:
  - url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/icons/128x128/otpclient_com.github.paolostivanin.OTPClient.jxl
    width: 128
    height: 128
  stock: com.github.paolostivanin.OTPClient
Launchable:
  desktop-id:
  - com.github.paolostivanin.OTPClient.desktop
Provides:
  binaries:
  - otpclient
Screenshots:
- default: true
  caption:
    C: Empty main window
  thumbnails:
  - url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-1_224x263@1.jxl
    width: 224
    height: 263
  source-image:
    url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-1_orig.jxl
    width: 501
    height: 590
- caption:
    C: Add menu
  thumbnails:
  - url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-2_224x263@1.jxl
    width: 224
    height: 263
  source-image:
    url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-2_orig.jxl
    width: 501
    height: 590
- caption:
    C: General menu
  thumbnails:
  - url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-3_224x263@1.jxl
    width: 224
    height: 263
  source-image:
    url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-3_orig.jxl
    width: 501
    height: 590
- caption:
    C: Settings menu
  thumbnails:
  - url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-4_224x257@1.jxl
    width: 224
    height: 257
  source-image:
    url: com/github/paolostivanin.OTPClient.desktop/7b47b8ece5cf35b3fa7f475d52f2eb4f/screenshots/image-4_orig.jxl
    width: 352
    height: 405
Releases:
- version: "5.2.0"
  type: stable
  unix-timestamp: 1789516800
  description:
    C: |-
      <p>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.</p>
      <ul>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>FIX: Steam tokens were exported with the issuer named twice, which strict third-party parsers reject</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>FIX: clicking another database in the sidebar while the current one was locked switched to it anyway,
        out from under the lock</li>
        <li>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</li>
        <li>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</li>
        <li>FIX: several memory leaks in the GUI, and one path where a dialog could be disposed twice</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>FIX: the notification carrying the code is now marked transient, so desktops keep it out of their
        notification history</li>
        <li>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</li>
        <li>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)</li>
        <li>NEW: start minimized to the tray, from Settings under Integration or with <code>otpclient --start-minimized</code>.
        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)</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>FIX: <code>otpclient-cli</code> 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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
        <li>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</li>
      </ul>
- version: "5.1.8"
  type: stable
  unix-timestamp: 1787270400
  description:
    C: |-
      <p>Bug-fix release. Minimize-to-tray did not work in the Flatpak: the switch was greyed out as if the
      desktop had no system tray, and granting the missing permission by hand still produced no icon. The sandbox
      refuses the process-derived bus name the tray asks to own, so the tray now registers with the tray host
      under its unique connection name instead, which needs no permission and works in any sandbox. The Flatpak
      was also missing the permissions Auto-Lock needs, so locking on screen lock silently did nothing; that
      is fixed in the Flathub packaging, though locking on suspend stays unavailable there.</p>
      <ul>
        <li>FIX: no tray icon appeared in sandboxed builds even with a tray host present, because the session
        bus refused the process-derived StatusNotifierItem name and the tray gave up. It now falls back to
        registering under its unique bus connection name, which is what Qt applications do, so the icon appears
        regardless of what the sandbox grants (Flathub #79)</li>
        <li>FIX: two sandboxed applications could not both show a tray icon: every Flatpak process sees itself
        as pid 2, so the process-derived StatusNotifierItem names collided and whichever lost the race silently
        got none. Both now get an icon (Flathub #79)</li>
        <li>PACKAGING: the Flatpak lacked the D-Bus permissions the tray and Auto-Lock need. Access to the
        StatusNotifierWatcher name un-greys the minimize-to-tray switch, which had reported "No system tray
        was detected on this desktop" on desktops that do run one, and access to the desktop screensaver services
        makes Auto-Lock on screen lock work, which had been a no-op. Auto-Lock on suspend stays unavailable
        in the Flatpak because it needs logind, which Flathub does not permit, so the "Could not subscribe
        to suspend events" warning remains there (Flathub #79)</li>
      </ul>
- version: "5.1.7"
  type: stable
  unix-timestamp: 1785801600
  description:
    C: |-
      <p>Minimize-to-tray is now offered in default builds. It had been an opt-in build flag because turning
      it on could strand the application: on a desktop with no system tray, closing the window hid it anyway
      and left OTPClient running invisibly, holding a decrypted database, with no icon to bring it back. The
      app now confirms a tray host is really there before it will hide to one, and restores the window if the
      tray goes away. The feature itself is still off by default in Settings.</p>
      <ul>
        <li>FIX: with minimize-to-tray enabled on a desktop that has no system tray (stock GNOME without the
        AppIndicator extension, i3bar, polybar), closing the window hid it with no icon to restore it, leaving
        an invisible process holding a decrypted database that only killall could stop. The window is now hidden
        only once a tray host has accepted the icon, and if the tray disappears while the window is hidden
        the window comes back (#405)</li>
        <li>BUILD: ENABLE_MINIMIZE_TO_TRAY now defaults to ON, so distribution packages offer the feature without
        a custom build. The tray has not needed libayatana-appindicator since it moved to a direct StatusNotifierItem
        implementation over GDBus, so this adds no dependency. The minimize-to-tray setting itself is unchanged
        and still defaults to off, and its switch is greyed out where no tray was detected (#405)</li>
      </ul>
- version: "5.1.6"
  type: stable
  unix-timestamp: 1784678400
  description:
    C: |-
      <p>Bug-fix release. Auto-Lock was effectively unusable: on any profile that enabled it without changing
      the timeout, the database re-locked about five seconds after every unlock, and the unlock prompt could
      not be dismissed and quit the whole application when closed, leaving Settings unreachable. The timeout
      now defaults to five minutes, and the unlock prompt is dismissable and returns to a locked screen instead
      of quitting.</p>
      <ul>
        <li>FIX: with Auto-Lock enabled but the timeout left at its default, the database re-locked roughly
        five seconds after each unlock. The idle timer counts seconds, but the default was 5 and documented
        as minutes; the default is now 300 seconds (five minutes), so profiles that never set a timeout pick
        up a sane value automatically (#467)</li>
        <li>FIX: the unlock prompt could not be dismissed and closing it quit the whole application, so Settings
        could not be reached while locked. Dismissing it (Escape, the dialog close button, clicking outside,
        or the window close button) now drops to the locked screen and keeps the toolbar reachable; the toolbar
        lock button doubles as an unlock button while locked, and an explicit Quit button remains on the prompt
        (#467)</li>
      </ul>
ContentRating:
  oars-1.0:
    violence-cartoon: none
    violence-fantasy: none
    violence-realistic: none
    violence-bloodshed: none
    violence-sexual: none
    drugs-alcohol: none
    drugs-narcotics: none
    drugs-tobacco: none
    sex-nudity: none
    sex-themes: none
    language-profanity: none
    language-humor: none
    language-discrimination: none
    social-chat: none
    social-info: none
    social-audio: none
    social-location: none
    social-contacts: none
    money-purchasing: none
    money-gambling: none