Skip to content

Release 2026-10-23 - (expected chart version 5.38.0) - #5645

Open
zebot wants to merge 37 commits into
masterfrom
release_2026-10-23_09_24
Open

zebot wants to merge 37 commits into
masterfrom
release_2026-10-23_09_24

Conversation

@zebot

@zebot zebot commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

[2026-10-23] (Chart Release 5.38.0)

Release notes

  • [Only relevant if you have overwritten oauth_scope directives in
    your nginx config]
    The nginz route configuration syntax changed:
    oauth_scope (a bare scope base, e.g. conversations_code) is
    deprecated in favor of oauth_scopes (whole scopes,
    e.g. ["read:conversations_code", "write-only:conversations_code"]).

    If you override nginz routes in your own values, migrate each
    oauth_scope entry to the equivalent oauth_scopes list;
    oauth_scopes wins where a route has both. If you use the bundled
    chart, there is nothing to do, it is already updated.

    The old directive and old oauth tokens remain valid with new
    wire-server, but we will remove the deprecated functionality in some
    future release.

    See docs/src/developer/reference/config-options.md,
    https://docs.wire.com/latest/developer/reference/oauth.html for more
    context. ([WPB-28193] Disentangle oauth scopes (write access should not imply read access). #5542)

API changes

  • Remove deprecated field profilePict from UserProfile. (Remove deprecated pict from user profile #5538)

  • Meeting responses on V19 endpoints (create, get, list, update, link refresh) expose a has_password field indicating whether the meeting's join link is password-protected. (WPB-28126: Expose has_password on meeting responses #5595)

  • Disentangle oauth scopes (write access should not imply read access).
    {PUT,DELETE} /meetings/<domain>/<id> are now OAuth-accessible via write-only:meetings / delete-only:meetings. ([WPB-28193] Disentangle oauth scopes (write access should not imply read access). #5542)

  • WPB-28222: add GET /calls/config/v3 with coturn native long-term TURN credentials #5590 API changes

    • Added GET /calls/config/v3 serving TURN credentials in coturn's native
      long-term credential format instead of zauth: username is <unix-expiry>:<uid>
      and credential is the base64-encoded HMAC-SHA1 of the username keyed with the
      coturn static-auth-secret. The endpoint is enabled by the new optional brig
      option turn.coturnSecret (path to the file containing the coturn
      static-auth-secret); while unset, /calls/config/v3 responds with 500.
      Enabling turn.coturnSecret requires the entire advertised TURN fleet to
      validate coturn native long-term credentials; turn.secret (zauth) remains
      authoritative for /calls/config and /calls/config/v2.
  • The meetings endpoints (POST /meetings, PUT /meetings/{domain}/{id}, GET /meetings/{domain}/{id}, GET /meetings/list) expose a link field on the meeting object starting at API version V19: an https join link carrying the meeting's live join code as key/code query parameters (<base>/meeting-join/?key=<codeKey>&code=<codeValue>&domain=<domain>). The field is present only when the meeting has a live join code; it is omitted otherwise (e.g. meetings created before this change, deployments whose code store cannot hold meeting codes, or multi-ingress deployments with no join-link URI configured for the user's domain). The V15-V18 endpoint shapes are unchanged. (WPB-28216: add POST /meetings/{domain}/{id}/link/refresh #5559)

  • Added the POST /mls/messages/targeted endpoint for persistent targeted MLS messages. (WPB-29005 persistent targeted MLS messages #5570, [fix] drop transient/targeted message if fed API version is unsupported #5634)

  • Added POST /mls/messages/transient-targeted for submitting batches of transient targeted MLS messages. Messages are delivered to the specified recipient clients and are not persisted. (WPB-29006 transient targeted MLS messages #5599, [fix] drop transient/targeted message if fed API version is unsupported #5634)

  • Added POST /mls/messages/transient for submitting a single transient broadcast MLS message. Messages are delivered to connected group members and are not persisted. (WPB-29007 transient broadcast MLS messages #5601, [fix] drop transient/targeted message if fed API version is unsupported #5634)

  • The meeting type is no longer accepted on PUT /meetings/{domain}/{id}.

    "recurrence": null in an update body is now honored as "unset the recurrence" on all API versions (V15–V19); previously it was rejected with a 400 decode error. (WPB-29119: Meeting type is no longer updatable #5577)

  • POST /meetings (V19) accepts an optional password field to password-protect the meeting's join link/code at creation time. (WPB-29268: optional password on POST /meetings #5588)

  • Meeting join links are now capability-bearing query-parameter URLs (<base>/meeting-join/?key=<codeKey>&code=<codeValue>&domain=<domain>), mirroring conversation join links. The join endpoints are POST /meeting/{domain}/{key}/{code}/join?password=… and the unauthenticated GET /meeting/{domain}/{key}/{code}/code-check?password=…: the stable key addresses the code row and the rotating code value is the capability, so refreshing a link invalidates every previously issued URL. (WPB-28216: add POST /meetings/{domain}/{id}/link/refresh #5559)

  • Add GET /meeting/{domain}/{key}/{code}/code-check?password=…, which works without authentication and returns the metadata (title, time, recurrence) of the meeting a join link resolves to (404 meeting-not-found for unknown, stale, or expired codes and for keys addressing a conversation code; 403 invalid-meeting-password when the link is password-protected and the password query param is missing or wrong). Add POST /meeting/{domain}/{key}/{code}/join?password=… for authenticated users, which joins the meeting's conversation like POST /conversations/join via the link's code access (re-joining is a no-op) and returns the meeting with its conversation view. Both replace the pre-release GET|POST /meeting-join?key=…&code=… routes. Known trade-off: the optional password travels as a query parameter, so it can appear in access logs and browser history (nginz masks password= in its sanitized access log); it only gates joining a single meeting, not an account. (WPB-28989: add /meeting/{domain}/{key}/{code}/{code-check,join} #5560)

Features

Bug fixes and other updates

Documentation

Internal changes

  • Create new backoffice endpoint to export active users by TeamID (Add backoffice endpoint for team member csv #5594)

  • Galley conversation subsystem: throw ConversationSubsystemError constructors
    directly instead of relying on mapErrors for a set of standalone exceptions
    (ChannelsNotEnabled, NotAnMlsConversation, MLSNonEmptyMemberList,
    NoBindingTeamMembers, BroadcastLimitExceeded,
    MLSFederatedOne2OneNotSupported, CreateConversationCodeConflict,
    InvalidTarget, MLSClientMismatch, MLSInvalidLeafNodeIndex,
    MLSUnsupportedProposal, MLSFederatedResetNotSupported,
    InvalidConversationPassword, AdminlessConversation). The corresponding
    ErrorS/Error entries and mapError lines are removed from
    Wire.ConversationSubsystem.Errors. No API, schema, or config change; the
    mapped error responses are observationally identical.
    Galley conversation subsystem: complete the ErrorS → ConversationSubsystemError migration. All remaining internal throws (conversation actions, MLS message path, OTR messages, codes/guest links, sub-conversations, NotConnected/MLSNotEnabled) now throw ConversationSubsystemError constructors directly; federation boundaries map via total cseToGalleyError/galleyErrorToCSE. Dead ErrorS chains (TooManyMembers, GroupIdVersionNotSupported), the per-tag HasConversationActionGalleyErrors family, and a stray generated libs/wire-subsystems/config are removed. No API, schema, or config change.
    Remaining ErrorS throws in Wire.ConversationSubsystem are migrated to
    ConversationSubsystemError (MLSSubConvUnsupportedConvType, MLS message path,
    conversation delete, cells state, conversation-code URI, conversation creation,
    MLS proposal failures). TeamSubsystem/TeamStore boundary functions
    (permissionCheck, lookupBindingTeam) are wrapped by local CSE variants
    (permissionCheckCSE, lookupBindingTeamCSE). The ErrorS machinery
    (ConversationSubsystemErrorEffects entries, mapError lines,
    RethrowErrors/ToGalleyRuntimeError instances, dead getMember, and
    Update.hs's -Wno-redundant-constraints) is removed, including the last
    four dead ErrorS rows in ConversationSubsystemErrorEffects and
    UpdateConversationAccessEffects.
    No API, schema, or config change. (WPB-25033: throw ConversationSubsystemError constructors directly in ConversationSubsystem #5348)

  • Updated email templates to v1.0.160 (WPB-25931: Update email templates to v1.0.160 #5572)

  • Add meeting invitation, update and cancellation email operations to the email subsystem (WPB-25930: add meeting email operations to the EmailSubsystem effect #5605)

  • added tests for basic federation use cases across Fed API versions (WPB-29135 test basic federation use cases across Fed API versions #5589)

  • Envoy-mode integration tests: teardown and hack/bin/integration-cleanup.sh now delete the Envoy Gateway proxies and federation Services that test runs create in envoy-gateway-system (deleting the test namespaces alone leaked them), and setup waits until all Gateways are programmed, as helmfile does not wait for the Envoy proxies. (envoy orphan cleanup #5630)

  • Add HIP-0015 helm.sh/images annotations to internal charts; hack/bin/set-wire-server-image-version.sh stamps the :do-not-use placeholder with the release version. (HIP-15 annotations for internal charts #5603)

  • wire-ingress: Use ListenerSets for application listeners and traffic policies.
    Requires Envoy Gateway >= 1.9; for 1.9, use Kubernetes 1.33–1.36 and Gateway API 1.6.1 standard CRDs plus matching Envoy Gateway extension CRDs.
    Federation requires extensionApis.enableLua: true in the controller configuration. (charts/wire-ingress: use ListenerSet by default #5591)

  • SBOM generation: add placeholder Helm values so charts render without errors in
    hack/bin/create-helm-sboms.sh. (fix make sboms-helm (SBOM creation) #5592)

Federation changes

VeryMilkyJoe and others added 30 commits October 6, 2026 10:41
* Remove deprecated pict field from user profile

Starting with V18, UserProfile does not contain profilePict anymore,
while for older versions the old schema will still be produced.

Note that on federation side, older versioned UserProfiles with an empty pict field are still used as to not introduce a new federated version.
Federated endpoints can be versioned in the future for UserProfile with the introduction of a new federated api version.
Master->Develop after release
* WPB-28216: add POST /meetings/{domain}/{id}/link/refresh

* WPB-28216: lift effectful storedMeetingToMeetingWithConversation in refreshMeetingLinkImpl

Fix rebase fallout so make c passes:
- lift the now-effectful storedMeetingToMeetingWithConversation call in
  refreshMeetingLinkImpl's MaybeT block (matching updateMeetingImpl)
- SetMeetingHasCode mock: StoredMeeting does not model the has_code
  column, so only bump updatedAt (mirrors the Postgres impl)
- InterpreterSpec: Meeting.link is Maybe HttpsUrl; expect Just link

* WPB-28216: address refresh-link review feedback (atomic rotation, drop has_code, optional password, revoke guest links)

* WPB-28216: ormolu import ordering

* WPB-28216: enforce meeting-link password via join-meeting-by-link route

- Add POST /meetings/{domain}/{id}/join (V19, ZLocalUser, read-only): resolves
  a meeting join link and enforces its optional password (403
  invalid-meeting-password on missing/wrong password, 404 for dead links).
  The live code row is the capability; a password supplied for an
  unprotected link is ignored, mirroring conversation join-by-code.
- Return JoinMeetingResult from the subsystem (errors as values) so
  interpreter behavior stays observable in unit tests; the galley handler
  maps it to route errors.
- GetMeetingCode now returns the stored hashed password alongside the code.
- Unit tests (password set/clear/wrong/missing/ignored, dead link, foreign
  domain) and integration tests (refresh revokes guest links, creator-only,
  request-level join flows); nginz route + changelog.

* WPB-28216: make meeting join links capability-bearing

Embed the rotating join-code value in the link URL
(<base>/<meetingId>/<code>) and require it on the join route
(POST /meetings/{domain}/{id}/join/{code}). The presented value is
compared constant-time against the live code row; a stale value
(superseded by a link refresh) yields 404, so refreshing a link now
genuinely revokes previously shared URLs. Password enforcement is
unchanged (403 invalid-meeting-password).

Also: unit + integration tests assert old-link revocation; changelog
wording per review.

* Potential fix for pull request finding 'Document the join endpoint's required code path segment'

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* WPB-28216: meeting join links as key/code/domain query params

Renders meeting links as <base>/meeting-join/?key=<codeKey>&code=<codeValue>&domain=<domain>
(mirroring conversation join links) and replaces the unreleased V19
POST /meetings/{domain}/{id}/join/{code} route with
POST /meetings/join?key=...&code=...: the stable code key addresses the
code row (new CodeStore.GetMeetingCodeByKey, Postgres-routed since
meeting codes are Postgres-only), the rotating code value is the
capability, so refreshing a link invalidates every previously issued
URL.

* WPB-28216: tolerate absent join-link config in Meetings integration tests

The default integration stack configures no conversationCodeURI, so the
V19 meeting object omits the link field entirely; read it via lookupField
and skip the link assertions there (the postgres integration job, which
configures the URI, exercises them). Also fix an hlint hint.

* WPB-28216: drop the join-meeting-by-link endpoint

Remove POST /meetings/join?key&code and everything only it used: the
JoinMeetingByLink effect, joinMeetingByLinkImpl, the JoinMeetingResult
type, the join-only GetMeetingCodeByKey store op (all interpreters),
the MeetingJoinRequest type, the InvalidMeetingPassword error, the
galley handler/wiring, the nginz route block, and their tests.

The capability-bearing link format (<base>/meeting-join/?key=...&code=...)
and password collection/storage on POST /meetings/{domain}/{id}/link/
refresh are kept; the stored password has no enforcer until a future
join endpoint lands.

* Update comments for refreshMeetingLinkImpl function

Clarify behavior when code store cannot hold meeting codes.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* WPB-28216: make meeting-link rotation and guest-link revocation atomic

Replace the separate createMeetingCode + deleteConversationCode calls in
refreshMeetingLinkImpl with a single CodeStore op, RotateMeetingCode:
the meeting-code upsert and the conversation guest-code delete commit
together in one Postgres transaction, so a crash can never leave the old
guest link usable after the meeting link has been replaced.

Routing spans both storage classes: meeting codes are Postgres-only, but
conversation codes are still read from Cassandra during migration, so
DualWrite revokes the Cassandra guest-code copy first (fail-safe: a
failure leaves the old meeting link valid, never a live bypass) before
the atomic Postgres rotate. Cassandra-only mode keeps revoking the guest
code and reports unsupported (False) as before. The pure mock mirrors
the semantics.

* Hello CI

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
)

Resolve a meeting join link (GET) and join the meeting's conversation
like POST /conversations/join (POST, via CodeAccess). Unlike the regular
meeting endpoints no creator or conversation membership is required;
expired, remote, or code-less links return 404 meeting-not-found.
Deliberately exempt from the guest-links policy: the meeting link is its
own capability (documented in-code). Includes unit tests
(MeetingsSubsystem.InterpreterSpec) and integration tests
(testMeetingLinkJoin{,NotFound,RemoteDomain}) plus changelog entry.
Starting with API version V19, the meeting `type` is set at creation
only: `PUT /meetings/{domain}/{id}` no longer accepts it. A body with
`type` and no other field is rejected with 403 invalid-op; `type`
alongside other fields is ignored. V15–V18 request shapes are unchanged
(one `UpdateMeeting` type now serves all versions; the legacy aliases
are removed).

Also fixes meeting-update decoding: an update body that omitted
`recurrence` previously decoded as "unset recurrence", silently
clearing the stored recurrence on every update. Omitting it now leaves
it unchanged; "recurrence": null explicitly unsets it.
* WPB-27369 wire-ingress: HA, PDB, spreads across AZ

The Envoy proxy fleet created by this chart now defaults to 2 replicas with a PodDisruptionBudget and advisory node/zone spread (`gateway.envoyProxy.replicas`, `.podDisruptionBudget`, `.topologySpreadKeys`). New opt-in `gateway.zoneAwareRouting.enabled` makes Envoy prefer backend pods in its own availability zone, cutting inter-AZ traffic cost on multi-zone clusters. New `gateway.annotations` and `gateway.infrastructure.labels`. See the wire-ingress README.

* reduce verbosity of comments

* changes

* ..

* tweak
…PI (#5582)

* implement federated dev api

* docs

* little additon to the docs

* changelog

* addressed PR issues

* Add federation API version regression tests

* revert irrelevant doc change

* addressing PR review comments

* removed unused function

* more issues addressed

* v0 and v1 disabling not supported anymore

* fixed log message

* linter

* make unversioned queries to galley federator in tests

* remove redundant ToSchema instance
…test setup (#5583)

* implement federated dev api

* all fed versions smoke test

* do not fail silently

* improve redis cluster init

* give healthchecks some more time

* added rabbitmq health check

* add some docs on how to run local legacy federation tests

* fix redis init script

* local docker configuration for v3

* support v3 in tests

* updated docs

* remove obsolete v3 settings

* docs on how to add a new pinned local version.

* add k8s integration configuration for federation v3

* documenting the CI setup for a new pinned legacy backend

* changelog

* addressed review comments

* fix database name for v3

* added rabbitMQ credentials for v2/3 in envrc

* fix local gundeck settings for fed v3

* update docs

* restrict tests to relevant versions 1 and 2
)

* basic federation tests across federation versions

* fix the docker compose setup for legacy versions

* changelog

* restore log level warn

* restore loglevel warn

* remove obsolete setting

* removed unused setting
* charts/wire-ingress: use ListenerSet by default

---------

Co-authored-by: Jan Schumacher <jan.schumacher@wire.com>
---------

Co-authored-by: Gautier DI FOLCO <gautier.difolco@wire.com>
* Add backoffice endpoint to get csv of teammembers
* Use wire/mirror-images for minio in fake-aws-s3 Helm chart
  Move the fix from Helmfile deployment to the chart itself to fix it.
* Use bitnamilegacy repo for legalhold's postgres image
  The bitnami repo is gone.
* SBOM: Add missing Helm value placeholders
  Otherwise the charts cannot be rendered by the SBOMs scripts.
Show that the contactable status changes to `non-contactable` when a
user deletes all of their clients.

This dynamic behaviour wasn't described by any test.
* nix: Upgrade to hasql 2.0.1.0

Broadly this required upgrading these things:
* arbiter
* hs-opentelemetry-* (due to arbiter)
* QuickCheck (due to arbiter)

Upgrading quickcheck caused a lot of version bound checks to fail, so a lot of
jailbreaking was necessary.

pqi-ffi and pqi-native are in haskell-pins but are not really used, this is
because they're a dependency of hasql test suite, but the test suite is
disabled. We will eventually need to use them anyway, so this will get fixed
in the next commits.

* wire-otel: Adapt for hs-opentelemetry-* 1.0

* extended: Adapt for hasql-2, use pqi-native first to try it out

* JobSubsystem.Migrations: Adapt for hasql-2

* JobSubsystem: Adapt for arbiter upgrade

* Replace deprecated withMaxSuccess with withNumTests

QuickCheck upgrade

* background-worker, galley: Adapt for arbiter upgrade

* Use pqi-ffi instead of pqi-native

pqi-native doesn't support some fields in config like `hostaddr`.

* Upgrade hasql-resource-pool

Inlcudes the fix for destroying dead connections

* Changelog

* Remove already done TODO
…ad access). (#5542)

---------

Co-authored-by: Gautier DI FOLCO <gautier.difolco@wire.com>
battermann and others added 7 commits October 21, 2026 13:41
* Clean up Envoy Gateway leftovers of integration test namespaces

* Wait for Envoy Gateways to be programmed in integration setup

* Apply suggestion from @blackheaven

Co-authored-by: Gautier DI FOLCO <gautier.difolco@wire.com>

---------

Co-authored-by: Gautier DI FOLCO <gautier.difolco@wire.com>
@zebot
zebot requested review from a team as code owners October 23, 2026 09:25
@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Oct 23, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist

Projects

None yet

Development

Successfully merging this pull request may close these issues.