Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2ef0044
WPB-21964: Add Wire Meetings endpoints
blackheaven Nov 24, 2025
ae23e5b
fix: rework feature flags (meeting, meeting_premium)
blackheaven Dec 10, 2025
3a3060f
feat(stern): Add Meeting and MeetingPremium feature flags to Stern API
blackheaven Dec 13, 2025
ab53c0e
feat(meetings): Replace payingTeam with meeting and meetingPremium fe…
blackheaven Dec 13, 2025
c1e17d6
fix: schema recurrence field
blackheaven Dec 13, 2025
759299a
docs(api): frequency doc
blackheaven Dec 13, 2025
7e83d14
docs: Add documentation for meeting and meetingPremium feature flags
blackheaven Dec 13, 2025
1ad5e1d
refactor: move MeetingId to Data.Id
blackheaven Dec 13, 2025
9c00b5c
feat: Add updated_at column to meetings table and update relevant fun…
blackheaven Dec 13, 2025
fb85f33
fix: list test name
blackheaven Dec 13, 2025
d203bb5
fix: conversation creatio permissions
blackheaven Dec 13, 2025
9f31a22
feat: Add recurrence tests and update existing tests to handle recurr…
blackheaven Dec 13, 2025
eb84493
feat: Add date validation tests for meeting creation and updates
blackheaven Dec 13, 2025
936258c
refactor: Move meetings migration to wire-subsystems
blackheaven Dec 13, 2025
08e1b7c
fix(meetings): Correct JSON paths in integration tests
blackheaven Dec 14, 2025
6d40beb
feat(meetings): Use lowercase for frequency serialization
blackheaven Dec 15, 2025
5d81620
refactor: apply suggestions in libs/wire-subsystems/src/Wire/Meetings…
blackheaven Dec 15, 2025
44faf70
refactor: clean integration test
blackheaven Dec 15, 2025
6fd5b24
fix(cleanup): ensure conversation is associated
blackheaven Dec 15, 2025
94c87bc
fix: listMeetingsImpl returns also meeting the user is a simple parti…
blackheaven Dec 15, 2025
ad40a6c
refactor: split clean up and regular meeting subsystem, partially mov…
blackheaven Dec 15, 2025
7f72dec
fix: patching meeting dates
blackheaven Dec 16, 2025
841e9c5
refactor(tests): use common status assertions
blackheaven Dec 16, 2025
84e6c4a
refactor: drop multi-qualified
blackheaven Dec 16, 2025
ff9aa66
fix: formatting
blackheaven Dec 16, 2025
0f74bc9
fix: hlint
blackheaven Dec 16, 2025
b4c0642
feature(background-worker): use cron
blackheaven Dec 17, 2025
eb048ef
fix: queries exclude expired meetings
blackheaven Dec 18, 2025
bb6636d
fix: formatting
blackheaven Dec 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.d/2-features/WPB-21964
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Add meetingPremium feature flag to distinguish premium teams from trial teams. Meetings created by premium team members are marked as non-trial. Public endpoints: GET/PUT /teams/:tid/features/meetingPremium. Internal endpoints: GET/PUT/PATCH /i/teams/:tid/features/meetingPremium and lock status management.

Add meeting feature flag to control access to the meetings API. When disabled, all meetings endpoints return 403 Forbidden. The feature is enabled and unlocked by default. Public endpoints: GET/PUT /teams/:tid/features/meeting. Internal endpoints: GET/PUT/PATCH /i/teams/:tid/features/meeting and lock status management.
4 changes: 4 additions & 0 deletions charts/background-worker/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ data:
{{toYaml .backendNotificationPusher | indent 6 }}
{{- with .backgroundJobs }}
backgroundJobs:
{{ toYaml . | indent 6 }}
{{- end }}
{{- with .meetingsCleanup }}
meetingsCleanup:
{{ toYaml . | indent 6 }}
{{- end }}
{{- if .postgresMigration }}
Expand Down
9 changes: 9 additions & 0 deletions charts/background-worker/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ config:
# Total attempts, including the first try
maxAttempts: 3

# Meetings cleanup configuration
meetingsCleanup:
# Delete meetings older than this many hours (48 hours = 2 days)
cleanOlderThanHours: 48.0
# Maximum number of meetings to delete per batch
batchSize: 1000
# Cron schedule for the cleanup job (0 * * * * = every hour)
schedule: "0 * * * *"

# Controls where conversation data is stored/accessed
postgresMigration:
conversation: postgresql
Expand Down
14 changes: 14 additions & 0 deletions charts/galley/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ data:
{{- if .settings.checkGroupInfo }}
checkGroupInfo: {{ .settings.checkGroupInfo }}
{{- end }}
{{- if .settings.meetings }}
meetings:
{{- if .settings.meetings.validityPeriodHours }}
validityPeriodHours: {{ .settings.meetings.validityPeriodHours }}
{{- end }}
{{- end }}
featureFlags:
sso: {{ .settings.featureFlags.sso }}
legalhold: {{ .settings.featureFlags.legalhold }}
Expand Down Expand Up @@ -218,5 +224,13 @@ data:
stealthUsers:
{{- toYaml .settings.featureFlags.stealthUsers | nindent 10 }}
{{- end }}
{{- if .settings.featureFlags.meeting }}
meeting:
{{- toYaml .settings.featureFlags.meeting | nindent 10 }}
{{- end }}
{{- if .settings.featureFlags.meetingPremium }}
meetingPremium:
{{- toYaml .settings.featureFlags.meetingPremium | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
11 changes: 11 additions & 0 deletions charts/galley/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ config:

checkGroupInfo: false

meetings:
validityPeriodHours: 48.0

# To disable proteus for new federated conversations:
# federationProtocols: ["mls"]

Expand Down Expand Up @@ -288,6 +291,14 @@ config:
defaults:
status: disabled
lockStatus: locked
meeting:
defaults:
status: enabled
lockStatus: unlocked
meetingPremium:
defaults:
status: enabled
lockStatus: unlocked
aws:
region: "eu-west-1"
proxy: {}
Expand Down
11 changes: 11 additions & 0 deletions deploy/dockerephemeral/federation-v0/galley.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ settings:
removal:
ed25519: /etc/wire/galley/conf/mls-private-key-ed25519.pem

meetings:
validityPeriodHours: 48.0

featureFlags: # see #RefConfigOptions in `/docs/reference`
sso: disabled-by-default
legalhold: whitelist-teams-and-implicit-consent
Expand Down Expand Up @@ -83,6 +86,14 @@ settings:
verificationExpiration: 86400
acmeDiscoveryUrl: null
lockStatus: unlocked
meeting:
defaults:
status: enabled
lockStatus: unlocked
meetingPremium:
defaults:
status: enabled
lockStatus: unlocked

logLevel: Warn
logNetStrings: false
Expand Down
11 changes: 11 additions & 0 deletions deploy/dockerephemeral/federation-v1/galley.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ settings:
guestLinkTTLSeconds: 604800
disabledAPIVersions: []

meetings:
validityPeriodHours: 48.0

featureFlags: # see #RefConfigOptions in `/docs/reference`
sso: disabled-by-default
legalhold: whitelist-teams-and-implicit-consent
Expand Down Expand Up @@ -97,6 +100,14 @@ settings:
limitedEventFanout:
defaults:
status: disabled
meeting:
defaults:
status: enabled
lockStatus: unlocked
meetingPremium:
defaults:
status: enabled
lockStatus: unlocked

logLevel: Warn
logNetStrings: false
Expand Down
11 changes: 11 additions & 0 deletions deploy/dockerephemeral/federation-v2/galley.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ settings:

disabledAPIVersions: []

meetings:
validityPeriodHours: 48.0

featureFlags: # see #RefConfigOptions in `/docs/reference`
sso: disabled-by-default
legalhold: whitelist-teams-and-implicit-consent
Expand Down Expand Up @@ -146,6 +149,14 @@ settings:
defaults:
status: enabled
lockStatus: unlocked
meeting:
defaults:
status: enabled
lockStatus: unlocked
meetingPremium:
defaults:
status: enabled
lockStatus: unlocked

logLevel: Warn
logNetStrings: false
Expand Down
48 changes: 48 additions & 0 deletions docs/src/developer/reference/config-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,54 @@ The `conferenceCalling` section is optional in `featureFlags`. If it is omitted

See also: conference falling for personal accounts (below).

### Meetings

The `meeting` feature flag controls whether a user can initiate a meeting. It is enabled and unlocked by default. If you want a different configuration, use the following syntax:

```yaml
meeting:
defaults:
status: disabled|enabled
lockStatus: locked|unlocked
```

These are all the possible combinations of `status` and `lockStatus`:

| `status` | `lockStatus` | |
| ---------- | ------------ | ------------------------------------------------- |
| `enabled` | `locked` | Feature enabled, cannot be disabled by team admin |
| `enabled` | `unlocked` | Feature enabled, can be disabled by team admin |
| `disabled` | `locked` | Feature disabled, cannot be enabled by team admin |
| `disabled` | `unlocked` | Feature disabled, can be enabled by team admin |

The lock status for individual teams can be changed via the internal API (`PUT /i/teams/:tid/features/meeting/(un)?locked`).

The feature status for individual teams can be changed via the public API (if the feature is unlocked).

### Meeting Premium

The `meetingPremium` feature flag controls whether a team has premium meeting features. When enabled, meetings created by team members are not marked as trial. When disabled, meetings are trial and limited to 25 minutes. It is enabled and unlocked by default. If you want a different configuration, use the following syntax:

```yaml
meetingPremium:
defaults:
status: disabled|enabled
lockStatus: locked|unlocked
```

These are all the possible combinations of `status` and `lockStatus`:

| `status` | `lockStatus` | |
| ---------- | ------------ | ------------------------------------------------- |
| `enabled` | `locked` | Feature enabled, cannot be disabled by team admin |
| `enabled` | `unlocked` | Feature enabled, can be disabled by team admin |
| `disabled` | `locked` | Feature disabled, cannot be enabled by team admin |
| `disabled` | `unlocked` | Feature disabled, can be enabled by team admin |

The lock status for individual teams can be changed via the internal API (`PUT /i/teams/:tid/features/meetingPremium/(un)?locked`).

The feature status for individual teams can be changed via the public API (if the feature is unlocked).

### File Sharing

File sharing is enabled and unlocked by default. If you want a different configuration, use the following syntax:
Expand Down
3 changes: 3 additions & 0 deletions integration/integration.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ library
Test.FeatureFlags.FileSharing
Test.FeatureFlags.GuestLinks
Test.FeatureFlags.LegalHold
Test.FeatureFlags.Meeting
Test.FeatureFlags.MeetingPremium
Test.FeatureFlags.Mls
Test.FeatureFlags.MlsE2EId
Test.FeatureFlags.MlsMigration
Expand All @@ -171,6 +173,7 @@ library
Test.Federator
Test.LegalHold
Test.Login
Test.Meetings
Test.MessageTimer
Test.MLS
Test.MLS.Clients
Expand Down
31 changes: 31 additions & 0 deletions integration/test/Test/FeatureFlags/Meeting.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2025 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Test.FeatureFlags.Meeting where

import Test.FeatureFlags.Util
import Testlib.Prelude

testPatchMeeting :: (HasCallStack) => App ()
testPatchMeeting = checkPatch OwnDomain "meeting" disabled

testMeeting :: (HasCallStack) => APIAccess -> App ()
testMeeting access =
mkFeatureTests "meeting"
& addUpdate disabled
& addUpdate enabled
& runFeatureTests OwnDomain access
31 changes: 31 additions & 0 deletions integration/test/Test/FeatureFlags/MeetingPremium.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2025 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Test.FeatureFlags.MeetingPremium where

import Test.FeatureFlags.Util
import Testlib.Prelude

testPatchMeetingPremium :: (HasCallStack) => App ()
testPatchMeetingPremium = checkPatch OwnDomain "meetingPremium" disabled

testMeetingPremium :: (HasCallStack) => APIAccess -> App ()
testMeetingPremium access =
mkFeatureTests "meetingPremium"
& addUpdate disabled
& addUpdate enabled
& runFeatureTests OwnDomain access
6 changes: 5 additions & 1 deletion integration/test/Test/FeatureFlags/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@ defAllFeatures =
"collabora" .= object ["edition" .= "COOL"],
"storage" .= object ["teamQuotaBytes" .= "1000000000000"]
]
]
],
"meeting" .= enabled,
"meetingPremium" .= enabled
]

hasExplicitLockStatus :: String -> Bool
Expand All @@ -252,6 +254,8 @@ hasExplicitLockStatus "sndFactorPasswordChallenge" = True
hasExplicitLockStatus "outlookCalIntegration" = True
hasExplicitLockStatus "enforceFileDownloadLocation" = True
hasExplicitLockStatus "domainRegistration" = True
hasExplicitLockStatus "meeting" = True
hasExplicitLockStatus "meetingPremium" = True
hasExplicitLockStatus _ = False

checkFeature :: (HasCallStack, MakesValue user, MakesValue tid) => String -> user -> tid -> Value -> App ()
Expand Down
Loading