v0.25.7
Released: 2026-04-26 · Channel: stable · Breaking: no · Security: yes
Summary
Closes the “kick is incomplete” thread the v0.25.6 sender-key fix opened, plus two finishing-touches on the multi-tenant deployment model. Three forward-secrecy fixes in the same class as v0.25.6, plus private-by-default for new workspaces and pre-assignable roles on community invites.
Security
WebSocket subscription drained on kick / leave / ban (high)
The per-channel broadcast forwarder that the WebSocket Subscribe client message spawns checked membership at subscribe time but not on each forwarded event. A user whose membership was revoked mid-session continued receiving ciphertext + metadata until they disconnected.
The forwarder now consults a per-(user, channel) revocation set in
ConnectionManager on every event; kick, leave, and ban
paths set the flag immediately. Set is cleared on legitimate
re-subscribe so a re-invited user works normally. Cost: one DashMap
read per forwarded message — nanosecond-level, dwarfed by the
JSON serialization already happening.
Community ban now rotates sender keys (urgent, sister of CHAT-115)
The community ban path removed membership rows but never deleted the banned user’s sender-key distributions or asked remaining members to rotate. The banned member retained chain-key seeds and could decrypt future ciphertext on those chains. v0.25.6 closed this gap on kick + leave; v0.25.7 closes it on ban.
Voluntary channel leave now rotates sender keys (urgent)
Same class, smaller surface. Self-leaving a channel via
POST /api/channels/{id}/leave now deletes the leaver’s
sender-key distribution and broadcasts
SenderKeyRotationRequired — mirrors the kick path
in routes/channels.rs:402-410.
Improved
Communities default to discoverable = FALSE
New workspaces are private-by-default. The invite-info endpoint
redacts community name + description for non-discoverable workspaces,
so a freshly-created internal/customer workspace no longer leaks its
identity to invite holders. Existing rows are not touched; flip via
PATCH /api/communities/{id} with
{"discoverable": true} if the workspace is meant to be
public.
Added
Invites can pre-assign a community role
POST /api/communities/{cid}/invites now accepts
grants_role: "moderator" | "admin". Authorization
mirrors set_member_role: only owners can mint
admin-grant invites; managers (admin or owner) can mint
moderator-grant invites. Role is applied immediately after
join_community on accept, with an audit log entry
(community_invite_role_grant). Removes the dual-step
“user joins → operator promotes” dance.
Migrations
056_discoverable_default_false.sql— flips column default for new rows; existing rows untouched.057_invite_grants_role.sql— addscommunity_invites.grants_rolewith check constraint ('moderator','admin', or NULL).
Upgrade path
Click Apply in the admin Updates tab. ~30 sec downtime; two additive migrations run during the orchestrator’s migrate phase. No client-side action needed.
Release artifacts
Container image pushed to
registry.seglamater.app/seglamater/chatalot, cosign-signed
against the published public key.