Tuwunel 1.9.3
September 25, 2026
New Features & Enhancements
- Remote profiles can be refreshed on demand, graciously contributed by @x86pup (64e1226, b1157d8).
!admin users refresh-profile <user>fetches a remote user's profile from their own server and drops every cached field that server no longer serves, such as a status the user has since cleared; local clients see the removal on their next sync.!admin users set-profile-keycan now also clear one cached field of a remote user, and the value returns on the next ordinary lookup if their server still serves it. Neither command runs automatically, and both accept only remote users this server already knows. Seedocs/moderation.md.
Bug Fixes
-
Sliding Sync works again for users with old-format join records. In 1.9.2, a user holding a join record written by Conduit, conduwuit, another Conduit-lineage fork, or Tuwunel before 1.4.3.1, and not rewritten since, got a 500 on every Sliding Sync request, logged as
u64 buffer underflow, and Element X sat in a restart loop. Legacy/syncfailed the same way for clients that requestprofile_fieldsin their filter. Such a record now reads as the earliest join position. The condition is per record, not per database: a join event processed by Tuwunel 1.4.3.1 or later rewrites the record, and a display name or avatar change sends one into every joined room, so a user who had changed their profile on such a release was spared while a neighbor with a stable profile on the same database was not. Upgrading is the whole fix; nothing migrates and nobody needs to rejoin. @drrossum reported the restart loop in (#598), @Reaster0 confirmed it on a database migrated from a Conduit-lineage fork, and @scvalex hit it while testing the nixpkgs backport of 1.9.2; the fix is courtesy of @x86pup. Sincere apologies to everyone whose Element X could not get past a sync. -
OIDC sessions carried over from a Conduit-lineage fork survive the upgrade again. The 1.9.2 migration that preserved imported token expiries stamped each such session with its long-past origin expiry, so its first request drew a soft logout (
M_UNKNOWN_TOKEN) and deleted its token. With no OIDC provider here, the default, the client could neither refresh nor sign out cleanly; the reporter's Element X sat in a 401 loop for forty minutes before a password sign-in. Adoption now waits until this server runs its own OIDC provider (well_known.clientplus anidentity_provideroroidc_native_auth); until then those sessions keep their origin lifetime, and enabling a provider signs them out once, cleanly. On a server without a provider, a database that already ran 1.9.2 is repaired on its first 1.9.3 start for every migrated session not used since, and each restored device is logged. A session used under 1.9.2 was deleted at that request; neither this release nor a rollback to 1.9.1 brings it back. Do not roll back to 1.9.2 after that first 1.9.3 start: 1.9.2 would stamp the restored sessions again and delete each at its next request, and the repair does not run a second time, so those sessions are lost. 1.9.1 and earlier are safe to return to. Thanks to @Reaster0, who reported (#602) with a proxy-log timeline and a code-level diagnosis and proposed the repair for databases 1.9.2 had already stamped; shipped by @x86pup. Sincere apologies to everyone 1.9.2 signed out. -
The Synapse-compatible admin join,
POST /_synapse/admin/v1/join/{room_id_or_alias}, no longer answers 403 "cannot join a room that is notpublic" for a private room. When this server is in the room and its join rule would refuse the user uninvited, the requesting admin now invites them first, matching Synapse; a restricted room gets the invite only when the user is outside its allowed rooms. The admin must be joined there with power to invite, and the!admin usersforce-join console commands are unchanged. Thank you @arnolicious for reporting (#603); credit to @x86pup for the fix. -
Debian and RPM upgrades skip the recursive ownership walk over a database directory already owned by
tuwunel:tuwunel, unless a legacy database was just adopted. The server keeps running until the package restarts it, so a file RocksDB removed mid-walk could fail thechown; on Debian that aborted package configuration, while the RPM script ignored the failure. Tip of the hat to @x86pup (afc1116).