Release notes
-
The PostgreSQL connection pool implementation was switched to
hasql-resource-pool.
TheagingTimeoutsetting is now ignored and should be treated as deprecated.
Pool metrics now include acquisition/session latency. (#5323) -
Background-worker now runs additional jobs and has new settings. The
jobssettings configure the dispatcher, worker, retry, shutdown, and reaper behavior, with defaults matching the existing behavior. The initial queues aremeetingsandconversations, with one worker pool assigned to each queue.Operators should size the background-worker PostgreSQL pool and PostgreSQL
max_connectionsfor this workload and the transient connection used while acquiring the migration lock; that connection is closed after migrations complete.jobs.workerThreadsdefaults to1.Both worker pools use the same PostgreSQL pool. Connections are borrowed for active job transactions and short-lived worker operations, rather than being reserved permanently per pool. LISTEN/NOTIFY is disabled, so the job runner does not open an additional listener connection.
The Helm chart sets
background-worker.terminationGracePeriodSecondsto40, providing a margin over the defaultjobs.gracefulShutdownTimeoutof30s. Adjust both settings together if changing the shutdown timeout. (#5289) -
- The
backgroundEffectsteam feature flag is deprecated (WPB-27912). Its
default is now enabled and locked, and the Helm configuration override for
backgroundEffectshas been removed fromcharts/wire-server. The flag's
data type and its public/internal HTTP endpoints are retained for backward
compatibility; any Helm overrides forbackgroundEffectsare now ignored and
can be removed. The public/internal HTTP endpoints return 404 at API version
v17 and remain available through v16; the flag type remains deprecated. The
aggregateGET /feature-configsandGET /teams/:tid/featuresendpoints
continue to includebackgroundEffectsat all API versions, including v17. (#5431)
- The
-
Make SCIM error responses comply with RFC7644. Any code that processes SCIM error responses must be changed to follow the standard, instead of the previous Wire implementation.
Previous schema (incompatible with RFC):
{ "code": 400, "label": "scim-error", "message": "{\"detail\":\"[...]\",\"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:Error\"],\"scimType\":\"invalidValue\",\"status\":\"400\"}" }New schema (RFC-compliant):
{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "400" "scimType": "invalidValue", "detail": "[...]", } ``` (#5439) -
SCIM: Make role and entitlements fields in user schema comply with RFC. Any code that processes SCIM users must be changed to follow the standard, instead of the previous Wire implementation.
Previous User schema (incompatible with RFC):
{ ... "roles": ["member"], "entitlements": ["some entitlement"], ... }New schema (RFC-compliant):
{ ... "roles": [{"value" : "member"}], "entitlements": [{"value" : "some entitlement"}], ... }For backwards compatibility, both fields still accept the old bare-string form on input. (#5440)
-
Added a new galley setting
settings.meetings.pastEditPeriod(default 24h): how far into the pastPUT /meetings/{domain}/{id}may move a meeting'sstart_time/end_time, so past and ongoing meetings can be corrected after the fact. Previously any start time in the past (beyond a 60s tolerance) was rejected while a meeting was still upcoming. Galley refuses to start ifpastEditPeriodis negative or greater thansettings.meetings.validityPeriod. (#5451) -
Update meeting conversations from
{private, invite}to{invite, code}so meetings can be joined by code. (#5464) -
The prevent adminless groups feature has known bugs. Disable and lock it by
Helm configuration for now. Development of this feature will continue, it
should just not be used in production as-is. (#5472) -
The
reaperchart no longer grants itselfcluster-adminand no longer uses an
unmaintained container image. Upgrading is a drop-inhelm upgrade; no manual steps.Two cases need action:
- If you override
imagein your values, update the override: the default changed from
docker.io/bitnamilegacy/kubectl:1.32.4todocker.io/alpine/kubectl:1.36.3. The
image must contain a POSIX shell at/bin/sh— distroless kubectl images do not work. - If you mirror images into a private registry (airgapped installs), add the new image.
See
charts/reaper/README.mdfor the image settings, the RBAC the chart now creates,
and the rest of the changes. (#5444) - If you override
-
- The
meetingsPremiumteam feature flag is deprecated (WPB-26771). It no
longer affects meeting behaviour: team meetings are always non-trial
regardless of its value. Its default is now enabled and locked, and the
Helm configuration override formeetingsPremiumhas been removed from
charts/wire-server. The flag's data type and its public/internal HTTP
endpoints are retained for backward compatibility but have no behavioural
effect; any Helm overrides formeetingsPremiumare now ignored and can be
removed. The public/internal HTTP endpoints now return 404 at API version v17
and remain available through v16; the flag type remains deprecated. The aggregateGET /feature-configsandGET /teams/:tid/featuresendpoints continue to includemeetingsPremiumat all API versions, including v17. (#5326)
- The
-
- Galley has a new optional
settings.meetings.emailconfiguration block
(WPB-27175) for sending meeting-invitation emails to invited external
addresses. It takes a requiredfromsender, an optionalreplyToaddress,
and atransportthat selects AWS SES or SMTP (the same shape Brig uses).
When the block is unset, meeting invitation emails are disabled. For SMTP,
setgalley.secrets.smtpPassword(mounted at
/etc/wire/galley/secrets/smtp-password.txt) and point
settings.meetings.email.smtp.passwordFileat that path; the Galley ConfigMap
injects it intotransport.smtpCredentials.smtpPassword, the same pattern
Brig uses forsmtp.passwordFile. This change adds the
configuration plumbing only; email sending itself lands in a follow-up. (#5346)
- Galley has a new optional
-
Starting at API version V17, the
Meetingtype returned and accepted by the
meetings endpoints carriestzid(IANA time zone) and drops the deprecated
trialfield;end_timeis retained on both V17 and V16. The operator config
galley.config.settings.meetings.legacyTimeZone(defaultEurope/Berlin) now
applies only to meetings created by legacy clients (API < V17); reads no longer
need it, astzidis persistedNOT NULL(backfilled toEurope/Berlin). (#5391)
API changes
-
SCIM user resources returned by spar now include
typeon stored email
addresses. Previously spar persisted notype, so SCIM PATCH operations with a
value-path filter likeemails[type eq "work"].value(as sent by Microsoft
Entra ID) never matched the stored entry and silently appended a duplicate
email instead of updating the address in place. Clients that compare full SCIM
user payloads rather than individual fields (e.g. strict equality on the
emailsarray) will see the additionaltypemember. (WPB-23434) (#5419) -
Introduced meeting-specific conversation lifecycle events:
conversation.create-meetingandconversation.delete-meeting. When a conversation of type meeting (group_conv_type: "meeting") is created or deleted, clients receive these instead ofconversation.create/conversation.delete. The payloads are identical to their non-meeting counterparts (conversation.delete-meeting, likeconversation.delete, carries nodata); only the eventtypediffers, so clients can handle meetings distinctly. (WPB-26626) (#5421) -
POST /meetings(create) andPUT /meetings/{domain}/{id}(update) now return a fullconversationobject alongside the existing meeting fields. The legacyqualified_conversationfield is retained for backward compatibility. (#5301) -
Roll back: do not include collaborator apps in get-apps end-point. (#5402)
-
The
backgroundEffectsteam feature endpoints are deprecated and return 404 for
clients on API version v17: the publicGET/PUT /teams/:tid/features/backgroundEffects
and the internal legacy lockPUT /i/teams/:tid/features/backgroundEffects/(un)?locked.
They remain available through v16. The aggregate endpoints
GET /feature-configsandGET /teams/:tid/featuresare unaffected and continue
to includebackgroundEffectsat all API versions: the aggregate feature list is
version-agnostic, like other version-gated features such as MLS. (#5431) -
Make scim error responses comply with RFC7644. (#5439)
-
SCIM: advertise all schemas used in User (fixes RFC compliance issue). (#5441)
-
SCIM: Make role and entitlements fields in user schema comply with RFC. (#5440)
-
The
mlsMigrationteam feature config now includes anallowManualMigration
boolean field (defaultfalse) that controls whether clients are permitted to
perform single-group (manual) MLS migrations. The field only steers client
behaviour (e.g. if a migration button is shown or not). It does not enforce
checks in the backend. (#5456) -
New oauth scopes for meetings for calendar integration. (#5462)
-
Meeting endpoints (
POST /meetings,PUT/DELETE /meetings/:domain/:id, meeting invitation endpoints): errors have dedicated descriptions. (#5455) -
PUT /meetings/{domain}/{id}now accepts an optionaltzidfield to update a
meeting's IANA time zone. (#5479) -
Finalize api version 17. (#5482)
-
To prevent security-relevant configuration mistakes, make configuration of
allowed IdP certificate fingerprints (idpCertFingerprintAllowlist) mandatory for
multi-ingress SSO. This will break existing multi-ingress SSO flows until
idpCertFingerprintAllowlistis configured! This breakage is unfortunately
necessary, because we're getting more lenient regarding the IdPs a user can use
to log in ("auto IdP migration"). Regular (non-multi-ingress) use cases are
unaffected. (#5327) -
+
GET /conversations/{domain}/{id}and the legacyGET /conversations/{id}now return 404 (no-conversation) when the conversation is a meeting, on API versions prior to V16, instead of returning the conversation withgroup_conv_type: null. The legacy batch endpointGET /conversations?ids=…— itself removed at V3, so only ever available on V1–V2 — likewise omits meeting conversations from its results. Meeting conversations remain fully accessible from V16 onwards. (WPB-26626) (#5382) -
The
meetingsPremiumteam feature endpoints are deprecated and return 404 for
clients on API version v17: the publicGET/PUT /teams/:tid/features/meetingsPremium
and the internal legacy lockPUT /i/teams/:tid/features/meetingsPremium/(un)?locked.
They remain available through v16. The flag has had no behavioural effect since
WPB-26771 (team meetings are always non-trial). The aggregate endpoints
GET /feature-configsandGET /teams/:tid/featuresare unaffected and continue
to includemeetingsPremiumat all API versions: the aggregate feature list is
version-agnostic, like other version-gated features such as MLS. (WPB-26771) (#5364) -
Reject meeting creation and update when the start time is in the past (with a 60-second tolerance for clock skew). Previously, meetings could be created with arbitrary past start times. (#5325)
-
GET /meetings/list and GET /meetings/{domain}/{id} no longer return 403 invalid-op when the caller's team has the
meetingsfeature disabled. The read endpoints now treat a disabled feature as "no meetings": GET /meetings/list returns 200 [], and GET /meetings/{domain}/{id} returns 404 meeting-not-found. Write operations (create, update, delete, invitation mutations) still return 403 invalid-op when the feature is disabled. Previously these read endpoints returned an undocumented 403 invalid-op for members of teams with the meetings feature disabled. (#5353) -
The meetings endpoints (POST /meetings, PUT /meetings/{domain}/{id}, GET /meetings/{domain}/{id}, GET /meetings/list) drop the deprecated
trialfield from theMeetingresponse starting at API version V17. On V15–V16 the field is still present but always returnsfalse(team meetings are never trial; see WPB-26771). The underlying storage is unchanged. (#5363) -
PUT /meetings/{domain}/{id} can now edit a meeting that has already started (an ongoing meeting). The start-time-not-in-the-past validation added by WPB-26773 previously rejected any update whose start_time was in the past, which also blocked legitimate edits to ongoing meetings — whose start time is naturally in the past; the check now applies only to meetings that have not started yet. Creating a meeting with a past start time, and moving an upcoming meeting's start time into the past, remain rejected (WPB-27465). (#5373)
-
Starting at API version V17, the
Meetingtype carries atzid(IANA time
zone) and drops the deprecatedtrialfield;end_timeis retained on both V17
and V16. A V17 update that supplies onlystart_timeleavesend_time
unchanged — passend_timeto reschedule the end. (#5391)
Features
-
Manual team invitations now conflict when a matching pending SCIM invitation already exists for the same team and email address. (#5400)
-
Add user contact-status enrichment to user listings based on available Proteus and MLS contact methods. (#5371)
-
Introduce schedulable background jobs, migrate meetings cleanup to the new job runner, and add the initial adminless reminder and deletion jobs. (#5289)
-
Skip senderless prevent-adminless deletion for federated conversations with remote members to prevent remote state drift. (#5425)
-
Add adminless-group reconciliation, teardown, and system events for member updates, reminders, and deletion. (#5357, #5390)
-
Filter Wire Meetings lifecycle events only on the originating client connection. (#5428)
-
When a team uses multiple SAML IdPs (one per ingress domain) in a multi-ingress
setup, users can now authenticate via any of the team's IdPs even if their
account was originally provisioned under a different one. Spar resolves the
correct account by email-based NameID lookup across all team IdPs and migrates
the user's SSO identity to the authenticating IdP transparently.Important: Email addresses (
NameIDs) must be unique across configured
IdPs! Otherwise, users may be logged into wrong accounts!Please refer to the documentation for further information. (#5212)
-
- Added meeting lifecycle events:
meeting.create,meeting.update, and
meeting.delete(WPB-26705). These websocket notifications are pushed to all
local members of the meeting's conversation on every successful create, update,
and delete operation. Each payload carries the eventtype, the meeting's
qualified ID in the top-levelqualified_idfield, the
qualified_conversation,qualified_from,via,time, and optionalteam.
Meeting events use a dedicated event envelope (not the conversation event
envelope). (#5330)
- Added meeting lifecycle events:
-
Added
meeting.member-addwebsocket event (WPB-27620). When a user becomes a
member of an MLS meeting conversation, ameeting.member-addlifecycle event is
pushed to the newly-added local members, alongside the existingmeeting.create,
meeting.update, andmeeting.deleteevents. The payload uses the same meeting
event structure as the other meeting lifecycle events. (#5383)
Bug fixes and other updates
-
When a user is put under SCIM control, any pending email-address update is now invalidated (the unvalidated email and its activation token are removed). Previously, team settings kept offering a "resend verification" action that could not succeed (failing with
403 managed-by-scim), and a stale activation link could still change a SCIM-managed user's email outside of SCIM. (#5333) -
Release a handle claimed after a SCIM invitation expired, before cleanup, preventing a subsequent team invitation from using that handle. (#5400)
-
SCIM PATCH now supports the
emailsmulti-valued attribute (e.g. Entra's
emails[type eq "work"].value), so user emails can be updated via SCIM. Identity
providers that previously hit acan not lens into multi-valued attributes yet
error when provisioning emails now succeed. (#5419) -
SCIM email metadata is now persisted and echoed verbatim. spar stores the
typeandprimarysub-attributes of the SCIM email entry it keeps (in
spar.scim_user_times) and echoes them back on GET/POST/PATCH exactly as the
IdP sent them, instead of synthesizing a hardcodedtypeof"work"(email
typevalues are limited to 64 characters). As a result, PATCH value-path
filters like Entra'semails[type eq "work"].valueand Okta's
emails[primary eq true].valuematch the stored entry for an in-place update
when (and only when) the IdP actually supplied that metadata at provisioning
time; users provisioned without it echo neither field. Since per RFC 7644
§3.5.2 anAddon a non-existing target creates it, a type-filter PATCH
against a user whose stored email carries no such metadata appends a new
entry (which the single-email reduction collapses back to the old address,
i.e. no visible change), while a primary-filter PATCH is a complete no-op. (#5419) -
SCIM user provisioning now rejects requests (HTTP 400) that mark more than one
email asprimary, an RFC 7643 §2.4 violation. Previously spar silently picked
one primary and dropped the rest, masking client-side misconfiguration. Requests
with zero or one primary email are unchanged. (#5419) -
Fixed asset uploads with non-ASCII filenames when audit logging is enabled. Audit-log metadata is now percent-encoded before being stored in S3 metadata headers and decoded when read back. (#5359)
-
Fix nginz routes for delete / update collaborator. Move collaborator CRUD api to galley. (#5334)
-
Users marked non-searchable are no longer returned across federation. (#5282)
-
If apps are re-enabled in the team, DO NOT re-activate any apps in the team. (#5347)
-
Wire Meetings lifecycle events (meeting.create, meeting.update, meeting.delete) are no longer delivered to the user who triggered the action, consistent with how other event types avoid echoing back to the originator. Previously the creator/updater/deleter received their own meeting event. (#5426)
-
Allow team admin to remove bot from all conversations, instead of crashing. (This is how it's already done in 'finishDeleteService'.) (#5450)
-
Fix openapi3 docs for oauth scopes. (#5457)
-
Enable claiming key packages for ephemeral users (#5339)
-
The federator internal listener's /i/status health check now correctly verifies the external listener is ready instead of checking itself, so readiness no longer reports up before the external federation listener is bound. (#5403)
-
Reorder SSO nginx locations to enforce correct rate limiting:
/sso/get-by-emailneeds to appear before/ssoin nginx's config, because
regex locations are matched in order (first-match), not by specificity. In
previous order/ssocaught before/sso/get-by-emailapplied the specific
5r/m rate limit, leaving it on the generic 50r/s limit. (#5341) -
Fixed Content Security Policy header scoping in multi-ingress Kubernetes configuration. CSP headers set via the Ingress nginx configuration-snippet are now properly scoped to exclude the webapp domain, preventing conflicts with the webapp's own CSP headers that are set independently. (#5432)
-
SCIM: Avoid assigning an already claimed handle to a user.
Before this if SCIM created a user with a handle already claimed by another user
the handle would get stored for the user even if the overall SCIM call fails. (#5475) -
SCIM PATCH on
emailsnow handles the emailtypeandprimary
sub-attributes per RFC 7644 §3.5.2.2 and RFC 7643 §2.5:
remove emails[type eq "work"].type(or.primary) unassigns just that
sub-attribute and keeps the entry (including the address and the other
sub-attribute) instead of deleting the whole record;replace/addwith an
explicit"value": nullunassigns the sub-attribute the same way; and a
filterlessremove emailsclears all email entries. Removing or nulling the
.valuesub-attribute is rejected with a 400 pointing at whole-entry removal,
since the address is the record's identity. As a consequence of preserving
explicitnullvalues in PATCH operations,replacewithnullon
displayName/externalId/activenow unassigns the attribute (RFC 7643 §2.5)
like the correspondingremovealready did, instead of failing with
"No value was provided". (#5419) -
Fixed a discrepancy between the canonical
searchVisibilityfeature key used in runtime JSON and the legacyteamSearchVisibilitykey used in YAML configuration. Both names are now accepted; no configuration changes or other operator actions are required. (#5338)
Internal changes
-
Fix integration test cleanup on federation instance V2. (#5447)
-
Update postgres schema dump. (#5461)
-
Move email template completeness tests from brig to wire-subsystems. (#5429)
-
Rename
Wire.ScimUserTimesStoretoWire.ScimUserMetaStore(ScimUserTimes->ScimUserMeta); the store also holds SCIM email metadata now. The Cassandra tablespar.scim_user_timesis unchanged. (#5419) -
Move
Spar.Sem.ReportertoWire.Reporter(#5377) -
Move
Spar.Sem.SamlProtocolSettingstoWire.SamlProtocolSettings(#5377) -
Move
Brig.Effects.JwtToolsinWire.JwtTools. (#5396) -
Move
Brig.BudgetinWire.BudgetStore. (#5397) -
Move
Galley.Effects.QueueinWire.BoundedQueue. (#5398) -
Move
Spar.Sem.ScimUserTimesStoretoWire.ScimUserTimesStore. (#5378) -
Move
Spar.Sem.DefaultSsoCodeinWire.DefaultSsoStore(#5379) -
Move
Spar.Sem.IdPRawMetadataStoretoWire.IdPRawMetadataStore. (#5380) -
Move
Spar.Sem.VerdictFormatStoreinWire.VerdictFormatStore. (#5388) -
Move
Spar.Sem.ScimExternalIdStoreinWire.ScimExternalIdStore. (#5392, #5423) -
Read the DPoP public key bundle once at startup and cache it, instead of
re-reading the file on every request; thePublicKeyBundleeffect is removed. (#5393) -
Move
Brig.Effects.UserPendingActivationStoreinWire.UserPendingActivationStore. (#5394) -
Move
Brig.Effects.SFTinWire.SFT. (#5395) -
In multi-domain (multi-ingress) mode, the
wire-ingresschart now applies the
httpRoute.annotationspassthrough to every per-domain HTTPRoute, so external-dns
weighted-record annotations (set-identifier/aws-weight) work across all backend
domains. Theservice.createtoggle also applies in multi-domain deployments. (#5307) -
Extract MLS key-package handling into a subsystem and split Cassandra access into a dedicated store. (#5368)
-
Added partial indexes and rewrote the meetings cleanup query so the background
worker stays fully index-backed as themeetingstable grows:idx_meetings_recurrence_eff_endonGREATEST(end_time, recurrence_until)
for bounded recurring meetings (covers the recurring branches of the list and
cleanup queries).idx_meetings_end_time_nonrecurringonend_timefor non-recurring meetings,
so cleanup can find expired non-recurring meetings without scanning
not-yet-expired recurring rows whose original slot is long past.
getOldMeetingsImplnow issues one bounded, index-backed query per meeting kind
and merges the two batches. (#5328)
-
Added a
meetings_recurrence_consistencyCHECK constraint so the recurrence
columns can never be left in a partially-set state (frequency is the master
switch; interval is required when set; recurrence_until stays optional for
open-ended recurring meetings). (#5328) -
The wire-ingress and nginx-ingress-services charts now expose annotation
passthroughs (httpRoute.annotationson the HTTPRoutes,ingress.annotationson
the Ingresses), so external-dns weighted records (set-identifier/aws-weight) can
be attached to both routers for a zero-downtime nginx-to-Envoy DNS cutover.
wire-ingress also gains aservice.createtoggle (default true) to reuse the
backend Services owned by nginx-ingress-services while both run in parallel. (#5358) -
Make haddocks more readable. (#5446)
-
When using the wire-ingress provided EnvoyProxy, ensure the request path's query string is removed from the logs, to ensure access_tokens passed as query string are not logged. Browsers are required to pass them on a query string on some endpoints such as /await. (#5361)
-
Moved the following endpoints from development version V17 to the new development version V18:
PUT /conversations/:domain/:cnv/members(rejection of replacements that would leave a group adminless),PUT /teams/:tid/features/preventAdminlessGroups(duration-string request body), andPOST /register(403 for SCIM-managed users changing their name). V17 behaves like V16 for these endpoints. API version V18 was created as a development version; V17 remains a development version until finalized. The changelog entry for the moved members endpoint is parked inchangelog.d/99-pending/, whichmk-changelog.shandmk-cleanup.shnow skip. (#5468) -
Automate license header updates in treefmt. (#5481)
-
Cannon now logs an error when registering a client's remote presence with
Gundeck fails, so operators can tell this apart from an actual
websocket/network issue (e.g.PongTimeoutcaused by Gundeck losing its Redis
connection). (#5454) -
The alpine base images used by the
cannon-configuratorinitContainer (wire-server
chart) and thejob-donecontainer (cassandra-migrationschart) are no longer
hard-coded. They can now be set viacannon.configuratorImage.{repository,tag,pullPolicy}
in thewire-serverchart andjobDoneImage.{repository,tag}in the
cassandra-migrationschart.The default was bumped from
alpine:3.21.3toalpine:3.24.1, since alpine 3.21
reaches end-of-support on 2026-11-01. The local integration stack'sinit_vhosts
container also moved fromalpine/curl:3.14(an Alpine 3.14 image last published
in 2021) toalpine/curl:8.21.0.Operators who mirror images into a private registry should make sure the new
alpine:3.24.1tag is cached, or overriderepositoryto point at their mirror.The chart release tooling (
hack/bin/set-wire-server-image-version.sh,
hack/bin/set-chart-image-version.sh) now anchors its version stamping to
repository: quay.io/wire/lines instead of matchingtag:by indentation, so
third-party image tags invalues.yamlare no longer overwritten with the
wire-server release version. (#5408) -
Updated email templates to v1.0.155 (#5344)
-
Fix
#sbomNix env / sbomnix usage by upgrading to latest stable version of
the latter. The issue was introduced by upgradingnixpkgsto 26.05. -
brig: Remove /i/users/rich-info (#5384)
-
remove sftd_disco (now lives in wireapp/wire-avs-service) (#5056)
-
Use wire image mirror for integration tests as
public.ecr.aws/bitnami/is no
longer available
(https://aws.amazon.com/blogs/containers/bitnami-image-removal-from-ecr-public/).
Docker Hub has strict rate-limiting. So, in lieu of better options, we now use
our own image cache atquay.io/wire/mirror-images. (#5360) -
Internal:
meetings.tzidis nowNOT NULL, backfilled toEurope/Berlin.
end_timeis the source of truth (there are noduration/duration_original
columns). (WPB-27553) (#5391) -
The
Z-Hostheader has been treated as domain, but used asText.
De-serializing and thus using it asDomainincreases type-safety and ensures
domain related semantics; e.g. case insensitivity in equality checks.
This solves aFUTUREWORKremark which was around for quite some time. (#5320)
Federation changes
deeplink.jsonnow contains a new optional fieldsupportEmailthat may be used by clients. (#5351)