Commit Graph
2875 Commits
Author SHA1 Message Date
Doug Lauder 3e38cbc5ca Add --workers flag to mmctl import process to control concurrency (#35582)
* Add --workers flag to mmctl import process to control concurrency

   The bulk import worker count was hardcoded to runtime.NumCPU(), causing
   high database load on the master during imports on live systems. This is
   particularly impactful for incremental Slack imports where all users are
   re-imported each time, generating 8-15 DB operations per user against
   the master (due to LockToMaster).

   The new --workers flag allows administrators to reduce concurrency
   (e.g., --workers 1) to minimize impact on live users at the cost of
   longer import duration. Defaults to 0 which preserves the existing
   runtime.NumCPU() behavior.

* Add max workers limit, capped at CPU Count * 4
2026-03-13 21:30:32 -04:00
Andre Vasconcelos e0fa9c7818 Bumping prepackaged GitLab plugin version to v1.12.1 (#35595) 2026-03-13 22:32:15 +02:00
LorenzoandJG Heithcock 742e0be950 Validate RefreshedToken differs from original invite token (#34864)
* Validate that RefreshedToken differs from original invite token in remote cluster confirmation

* Add unit test for MM-67098

---------

Co-authored-by: JG Heithcock <jgheithcock@gmail.com>
2026-03-13 19:07:40 +00:00
Carlos Garcia c9a4092ac0 keeps plugin config on reenablement (#35545)
* keeps plugin config on reenablement

* fixes local config patch on plugin reenablement
2026-03-12 19:36:05 +01:00
Maria A Nunez 2efee7ec28 Add single-channel guests filter and channel count column to System Console Users (#35517)
* Add single-channel guests filter and channel count column to System Console Users

- Add guest_filter query parameter to Reports API with store-level
  filtering by guest channel membership count (all, single_channel,
  multi_channel)
- Add channel_count field to user report responses and CSV exports
- Add grouped guest role filter options in the filter popover
- Add toggleable Channel count column to the users table
- Add GuestFilter and SearchTerm to Go client GetUsersForReporting
- Add tests: API parsing, API integration, app job dedup, webapp utils,
  E2E column data rendering

Made-with: Cursor

* Fix gofmt alignment and isolate guest store tests

- Align GuestFilter constants to satisfy gofmt
- Move guest user/channel setup into a nested sub-test to avoid
  breaking existing ordering and role filter assertions

Made-with: Cursor

* Exclude archived channels from guest filter queries and ChannelCount

The ChannelMembers subqueries for guest_filter (single/multi channel)
and the ChannelCount column did not join with Channels to check
DeleteAt = 0. Since channel archival soft-deletes (sets DeleteAt) but
leaves ChannelMembers rows intact, archived channel memberships were
incorrectly counted, potentially misclassifying guests between
single-channel and multi-channel filters and inflating ChannelCount.

- Join ChannelMembers with Channels (DeleteAt = 0) in all three
  subqueries in applyUserReportFilter and GetUserReport
- Add store test covering archived channel exclusion
- Tighten existing guest filter test assertions with found-flags
  and exact count checks

Made-with: Cursor

* Exclude DM/GM from guest channel counts, validate GuestFilter, fix dropdown divider

- Scope ChannelCount and guest filter subqueries to Open/Private channel
  types only (exclude DM and GM), so a guest with one team channel plus
  a DM is correctly classified as single-channel
- Add GuestFilter validation in UserReportOptions.IsValid with
  AllowedGuestFilters whitelist
- Add API test for invalid guest_filter rejection (400)
- Add store regression test for DM/GM exclusion
- Fix role filter dropdown: hide the divider above the first group
  heading via CSS rule on DropDown__group:first-child
- Update E2E test label to match "Guests in a single channel" wording

Made-with: Cursor

* Add store test coverage for private and GM channel types

Private channels (type P) should be counted in ChannelCount and guest
filters, while GM channels (type G) should not. Add a test that creates
a guest with memberships in an open channel, a private channel, and a
GM, then asserts ChannelCount = 2, multi-channel filter includes the
guest, and single-channel filter excludes them.

Made-with: Cursor

* Add server i18n translation for invalid_guest_filter error

The new error ID model.user_report_options.is_valid.invalid_guest_filter
was missing from server/i18n/en.json, causing CI to fail.

Made-with: Cursor

* Make filter dropdown dividers full width

Remove the horizontal inset from grouped dropdown separators so the
system user role filter dividers span edge to edge across the menu.
Leave the unrelated webapp/package-lock.json change uncommitted.

Made-with: Cursor

* Optimize guest channel report filters.

Use per-user channel count subqueries for the single- and multi-channel guest filters so the report avoids aggregating all channel memberships before filtering guests.
2026-03-12 12:50:53 -04:00
Bill Gardner 5646f4aa5c Update plugin-calls to v1.11.4 (#35561) 2026-03-12 11:40:38 -04:00
52858082fe Anonymous URLs (#35493)
* COmposing messages with redacted URLs

* Handled non member channels

* Some refinements

* Optimizations

* lint fixes

* cleaned up hasObfuscatedSlug test

* Fixed a test

* Added system console setting

* WIP

* fixed channel seelection double selection bug

* LInt fixes

* i18n fixes

* fixed test

* CI

* renamed setting

* lint fixes

* lint fixes

* WIP

* Combined TeamSignupDisplayNamePage and TeamUrl component into a single CreateTeamForm component

* Converted CreateTeamForm to functional component

* Refactored to mnake code cleaner

* Handle team creation with setting enabled

* Skipped team URL step if secure URL feature is enabled

* Managed button text and steps in team creation flow

* lint fixes

* Don't register team URL path when using secure URL

* Display team display name instead of name in system console top nav bar

* Fixed tests

* Fixed coderabbit issues

* Fixed type errors

* Optimization

* improvements

* Handled API errors during team creation when using secure URL setting

* Some refinements

* Added test

* Updaetd tests, and trimming when reading instead of writing

* Added tests for new components

* Added BackstageNavbar tests

* Restored package lock

* lint fix

* Updaetd plugin API

* Updated team creation tests

* Added tests for ChannelNameFormField

* Added plugin API tests

* Updated API terst

* Review fixes

* Added test for ConvertGmToChannelModal component

* Added EA license check for secure urls feature

* restored package lock

* Fixed GM conversion test

* Fixed team creation tests

* remove message composition changes

* remove message composition changes

* remove message composition changes

* restored a file

* lint fix

* renamed feature

* used model.SafeDereference

* Added E2E tests

* add secure URL Playwright coverage

Expand the secure URLs Playwright coverage to validate creation, routing, rename flows, system console configuration, and search/navigation behavior while adding the page objects needed to keep the tests maintainable.

Made-with: Cursor

* rename secure URLs copy to anonymous URLs

Align the admin console and Playwright coverage with the Anonymous URLs feature name while preserving the existing UseAnonymousURLs config behavior and validating the renamed test surfaces.

Made-with: Cursor

* Update team creation CTA for anonymous URLs

Show Create in the single-step anonymous URL flow while preserving Next and Finish in the standard team creation flow. Update unit and Playwright coverage to match the revised create-team UX.

Made-with: Cursor

---------

Co-authored-by: maria.nunez <maria.nunez@mattermost.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-12 10:32:29 -04:00
Andre Vasconcelos 608c009e4f Bumping prepackaged MS Teams Meetings plugin version to 2.4.1 (#35564) 2026-03-12 14:56:45 +02:00
Doug Lauder 162ed1bacd MM-67684 Separate shared channel permissions from secure connection permissions (#35409)
* Channel sharing operations (invite, uninvite, list shared channel remotes)
now require ManageSharedChannels instead of ManageSecureConnections, allowing
customers to delegate channel sharing without granting full connection management access.
Endpoints serving both roles (getRemoteClusters, getSharedChannelRemotesByRemoteCluster) accept either permission.

Also adds RequirePermission helpers on Context to reduce boilerplate across all remote cluster and shared channel handlers, and fixes a bug where invite/uninvite checked ManageSecureConnections but reported ManageSharedChannels in the error.
2026-03-11 15:53:06 -04:00
560ee5c598 [MM-67626] Update Playbooks plugin to v2.8.0 (#35549)
* [MM-67626] Update Playbooks plugin to v2.8.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Prepackage FIPS version for Playbooks

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
2026-03-11 11:02:36 +00:00
Carlos Garcia 3057ae7e83 MM-67646 slack import improvements (#35490)
* improves logging during slack import

* add imported users with no password and force reset flow

* use i18n key ids during test
2026-03-11 11:26:50 +01:00
b6e5264731 [MM-67739] Rename SlackAttachment to MessageAttachment across the codebase (#35445)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-10 16:37:21 +01:00
Ibrahim Serdar Acikgoz ada82304b0 implement property field seatch within access control policies (#35494) 2026-03-10 16:13:00 +01:00
Maria A Nunez 461db71178 Add single-channel guest tracking and reporting (#35451)
* Add single-channel guest tracking and reporting

- Add AnalyticsGetSingleChannelGuestCount store method to count guests in exactly one channel
- Exclude single-channel guests from active user seat count in GetServerLimits
- Add single-channel guest count to standard analytics response
- Add Single-channel Guests card to System Statistics page with overage warning
- Add Single-channel guests row to Edition and License page with overage styling
- Add dismissible admin-only banner when single-channel guest limit is exceeded
- Gate feature behind non-Entry SKU and guest accounts enabled checks
- Re-fetch server limits on config changes for reactive UI updates
- Fix label alignment in license details panel

Made-with: Cursor

* Refine single-channel guest tracking

- Remove license GuestAccounts feature check from shouldTrackSingleChannelGuests (only config matters)
- Re-add getServerLimits calls on page mount for fresh data
- Remove config-change reactivity code (componentDidUpdate, useEffect)
- Add server i18n translations for error strings
- Sync webapp i18n via extract
- Add inline comments for business logic
- Restore struct field comments in ServerLimits model
- Add Playwright E2E tests for single-channel guest feature
- Fix label alignment in license details panel

Made-with: Cursor

* Guests over limit fixes and PR feedback

* Fix linter issues and code quality improvements

- Use max() builtin to clamp adjusted user count instead of if-statement (modernize linter)
- Change banner type from ADVISOR to CRITICAL for proper red color styling

Made-with: Cursor

* Fix overage warnings incorrectly counting single-channel guests

Single-channel guests are free and should not trigger license seat
overage warnings. Update all overage checks to use
serverLimits.activeUserCount (seat-adjusted, excluding SCG) instead
of the raw total_users_count or TOTAL_USERS analytics stat.

- UserSeatAlertBanner on License page: use serverLimits.activeUserCount
- UserSeatAlertBanner on Site Statistics page: use serverLimits.activeUserCount
- ActivatedUserCard display and overage check: use serverLimits.activeUserCount
- OverageUsersBanner: use serverLimits.activeUserCount

Made-with: Cursor

* Use license.Users as fallback for singleChannelGuestLimit before limits load

This prevents the SingleChannelGuestsCard from showing a false overage
state before serverLimits has been fetched, while still rendering the
card immediately on page load.

Made-with: Cursor

* Fix invite modal overage banner incorrectly counting single-channel guests

Made-with: Cursor

* Fix invitation modal tests missing limits entity in mock state

Made-with: Cursor

* Fix tests

* Add E2E test for single-channel guest exceeded limit scenario

Made-with: Cursor

* Fix TypeScript errors in single channel guests E2E test

Made-with: Cursor

* Fix channel name validation error caused by unawaited async getRandomId()

Made-with: Cursor

* Add contextual tooltips to stat cards when guest accounts are enabled

Made-with: Cursor

* Code review feedback: query builder, readability, tooltips, and alignment fixes

Made-with: Cursor

* Fix license page tooltip alignment, width, and SaveLicense SCG exclusion

Made-with: Cursor

* Fix banner dismiss, license spacing, and add dismiss test

Made-with: Cursor

* Exclude DM/GM channels from single-channel guest count and fix E2E tests

Filter the AnalyticsGetSingleChannelGuestCount query to only count
memberships in public/private channels, excluding DMs and GMs. Update
store tests with DM-only, GM-only, and mixed membership cases. Fix E2E
overage test to mock the server limits API instead of skipping, and
correct banner locator to use data-testid.

Made-with: Cursor
2026-03-10 10:31:10 -04:00
a81c8c2993 Show priority badges in permalink previews (#35532)
* Add agent-browser skill

* Update AGENTS.CURSOR.md

* Add guidance for localization

* Fix permalink preview priority badges

Co-authored-by: Nick Misasi <nick13misasi@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-03-10 10:17:59 -04:00
e5f4b982e5 Add operation tracking fields to bridge client calls (#35514)
* Add operation tracking fields to bridge client CompletionRequest calls

Populate UserID, Operation, and OperationSubType on CompletionRequest
for recaps (SummarizePosts) and message rewrite (RewriteMessage) so
token usage logs show correct values instead of defaults.

Also bumps mattermost-plugin-ai v1.8.1 → v1.12.0 which adds the
Operation/OperationSubType fields to the bridgeclient struct.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address PR feedback: normalize rewrite action and use session-derived userID

- post.go: Add normalizeRewriteAction() that validates action against a
  whitelist of known RewriteAction values, mapping unknown values to
  "unknown" before assigning to OperationSubType.
- summarization.go: Use sessionUserID (derived from rctx.Session().UserId)
  instead of the userID parameter for tracking, ensuring operation
  tracking always uses the authenticated session user.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-10 06:49:18 -07:00
Carlos Garcia 5a1ea95044 encode special characters on some error pages (#35492) 2026-03-10 12:54:42 +01:00
Christopher Poile 7e0af2de57 MM-67540 - Align Elasticsearch backfill throttle to 10k requests/sec (#35539)
The OpenSearch implementation used 10,000 requests/sec but
Elasticsearch was set to 1,000. Align both to 10,000.
2026-03-09 15:01:58 -04:00
David Krauser c0c2ff2ad9 [MM-67314] Fix system bot DM restriction bypass (#35477)
When TeamSettings.RestrictDirectMessage is set to "team", the system bot could not create DM channels with users on different teams (or no shared team). This broke SendTestMessage, CheckPostReminders, and other background jobs that use an empty session context.

The existing bypass in GetOrCreateDirectChannel only covered bots owned by the current session user or a plugin. The system bot is owned by a system admin, so it failed the ownership check and hit the common-team guard.

Changes:
- Rename IsBotOwnedByCurrentUserOrPlugin to IsBotExemptFromDMRestrictions to better reflect its purpose
- Add an explicit system bot exemption (bot.Username == BotSystemBotUsername) as the first check in the function
- Add tests covering the system bot exemption with both empty and user sessions
2026-03-09 14:08:30 -04:00
Christopher Poile 2ada8d7659 MM-67540 - Allow searching public channel messages without channel membership (#35298)
* UpdateByQuery methods for channel_type; rewrite reindexChannelPosts

log pre-fetch error in channel Update and upgrade reindexChannelPosts to error level

* add backfill orchestration, config listener, webapp toggle changes

fix misleading backfill complete log when SaveOrUpdate fails

* add integration & unit tests for public channel search and backfill

* fix nil pointer dereference on UpdateByQuery response and log partial failures

* add tests for compliance mode override and P channel post leakage

* update system console snapshots

* add instructions to error message

* improve compliance-mode test

* getAllChannels doesn't filter by O/S, need to do ourselves

* in search, load channel info for channels we're not a member of

* blank commit -- something is wrong with github, maybe this will help

* improve channelType passing; error msg; simplify settings naming

* debug logging for timing backfill and channel change; TO BE REVERTED

* fix getMissingChannelsFromFiles in search as well

* blank commit
2026-03-09 14:07:44 -04:00
Alejandro García MontoroandMattermost Build 79ee7d9e16 MM-67686: Elasticsearch indexing job progress estimation (#35433)
* Improve job progress estimation with no data

For the Elasticsearch indexing job, we compute the job progress
executing analytics queries to get the total number of posts, channels,
users and files in the database.

Until now, if that call failed, we instead used an estimate. That
estimate is a hardcoded number that is in no way related to the server
data. If that estimate was smaller than the number of already processed
entities, the job progress would show up as larger than 100%.

This commit changes that behaviour by caching the result of the
analytics query:

1. If the analytics query succeeds, we store that value in the job data.
2. If the analytics query fails, we pick a value for the total as
   follows:
   - Use the value previously stored in the job data if available.
   - If not, use the hardcoded estimate.
   - If the hardcoded estimate is smaller than the current count of
     processed entities, use that count instead.

* Add defensive code against division by zero

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-09 17:04:07 +00:00
Weblate (bot)andmaster7 dc035b8f09 Translations update from Mattermost Weblate (#35531)
* Translated using Weblate (Polish)

Currently translated at 96.0% (6775 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (Polish)

Currently translated at 96.3% (6799 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (Polish)

Currently translated at 96.6% (6820 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (Polish)

Currently translated at 96.9% (6840 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (Polish)

Currently translated at 97.2% (6860 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/

---------

Co-authored-by: master7 <marcin.karkosz@rajska.info>
2026-03-09 14:30:33 +01:00
f1b9aa052e Rename Content Flagging to Data Spillage Handling (#35407)
* Rename Content Flagging to Data Spillage Handling

Update all user-facing text to use "Data Spillage Handling" and
"Quarantine for Review" terminology. Rename i18n keys that referenced
content flagging. Auto-patch bot display name on pre-existing servers.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fixed searchable stringgs

* Revert unintended package-lock.json changes

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix i18n extract check: correct typo and key ordering

Fix "posed" -> "posted" typo in keep/remove quarantine modal
defaultMessages. Move admin.contentFlagging.title to correct
alphabetical position in en.json.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix webapp tests for Data Spillage Handling rename

Update test assertions to match renamed i18n strings:
notification settings, content reviewers, and additional
settings tests now expect the new quarantine terminology.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Use translatable i18n strings for notification messages

Replace hardcoded "flagged for review" notification templates with
i18n.T() calls using "quarantined for review" terminology. Add six
new server i18n keys for author, reporter, and reviewer notifications.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix server i18n key mismatches and update test assertions

Rename remaining app.content_flagging.* keys to app.data_spillage.*
in server/i18n/en.json to match Go code references. Fix the
quarantine_post_confirmation key name. Update test assertions to
match new "quarantined for review" terminology.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix gofmt formatting in content_flagging.go

Co-authored-by: Cursor <cursoragent@cursor.com>

* Prevent nil bot on PatchBot failure in getContentReviewBot

Use a separate variable for PatchBot result so the original bot
is preserved if the display name update fails.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Reorder server i18n keys after extract

Run mmgotool i18n extract to sort entries into correct
alphabetical order.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Replace i18n.T() with fmt.Sprintf for notification messages and fix test assertions

Use direct string formatting for bot notification messages instead of
i18n translation keys, which were being removed by mmgotool i18n extract
due to indirect key references. Also update test expectations for renamed
error keys (content_flagging -> data_spillage).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Update default quarantine reasons to DISC-aligned terminology

Replace generic content moderation reasons with defense/intelligence
sector terminology: Classification mismatch, Need-to-know violation,
PII exposure, OPSEC concern, CUI violation, Unauthorized disclosure,
and Other. Updated across model, API tests, webapp tests, and e2e tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Adding a string missing from bad merge

* Update remaining flagged terminology and icon for data spillage rename

- Change post menu icon from flag-outline to alert-outline
- Update reviewer notification: "quarantined" -> "submitted" a message
- Update action notifications: "flagged message" -> "quarantined message"
- Update modal errors: "flagging" -> "quarantining" this message
- Update report title: "flagged" -> "submitted" a message for review
- Update e2e page object locator for renamed menu item

Made-with: Cursor

* Fix tests

* Fix quarantine icon alignment in post dot menu

Use AlertOutlineIcon React component with size={18} instead of raw
<i> tag to match the sizing of all other menu item icons.

Made-with: Cursor

* Fixed E2E tests

* Missing test fix

* Fix E2E tests

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-06 21:15:01 -05:00
Doug Lauder e31f471498 MM-67647 Add roles for shared channels management (#35354)
* Add shared_channel_manager and secure_connection_manager built-in roles

  Introduce two new delegated admin roles for granular Shared Channels
  permission management, allowing admins to assign shared channel and
  secure connection management to specific non-admin users without
  granting full System Admin or System Manager access.

  - shared_channel_manager: grants manage_shared_channels permission
  - secure_connection_manager: grants manage_secure_connections permission

  Includes server role definitions, app migrations, permissions migrations,
  System Console UI support, and API permission tests.
2026-03-06 10:51:21 -05:00
Guillermo Vayá f5fe8ded6b [MM-67377] Fix (#35336)
fix MM-67377
2026-03-06 13:39:48 +01:00
edgarbellot f542d7ca18 [MM-67791] Use atomic token consumption for guest magic links (#35489)
#### Summary

Use the atomic `ConsumeOnce` pattern for guest magic link token consumption, consistent with how SSO code exchange tokens are already handled.

#### Ticket Link

https://mattermost.atlassian.net/browse/MM-67791

#### Release Note

```release-note
Improved token handling in the guest magic link authentication flow.
```
2026-03-06 10:47:55 +01:00
Eva Sarafianou 56f51d7df2 Use standard session handler for updateUserAuth endpoint (#35488)
Change the /api/v4/users/{user_id}/auth endpoint to use
APISessionRequired instead of APISessionRequiredTrustRequester.

This endpoint is a JSON API called via XHR and does not need
the TrustRequester flag which is intended for directly-requested
resources like images and file downloads.

Made-with: Cursor
2026-03-06 08:14:22 +02:00
Ben SchumacherandClaude Opus 4.6 99d119cf85 [MM-66846] Fix missing ES version and plugins in diagnostics (#35475)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 23:55:32 +01:00
Nick MisasiandClaude Opus 4.6 cbdf5536fd Add structured JSON output for recap summarization (#35496)
* Add structured outputs, response sanitization, and session context for recaps

- Wrap BridgeClient to strip markdown code fencing from LLM JSON responses,
  using explicit delegation to prevent unsanitized methods from leaking
- Add JSONOutputFormat schema to SummarizePosts for structured LLM output
- Pass user session in recap worker context for session-dependent code paths
- Pre-parse min plugin version semver at package level to avoid repeated parsing
- Hoist static JSON schema to package-level var to avoid per-call allocation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix stripMarkdownCodeFencing to handle single-line fenced payloads

Address CodeRabbit feedback: the function previously returned the original
string when fenced JSON had no newline (e.g. ```json {"a":1}```), which
would break downstream JSON parsing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Handle case/spacing variants for single-line fenced language tags

Address CodeRabbit feedback: use case-insensitive comparison for the
"json" language tag and check for whitespace separator, so inputs like
```JSON {"a":1}``` are handled correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Revert BridgeClient wrapper and keep only structured output changes

Remove the BridgeClient wrapper, stripMarkdownCodeFencing, and semver
pre-parse from agents.go. The scope of this PR is limited to adding
JSONOutputFormat structured outputs for recaps and the worker session
context fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix lint: use any instead of interface{} and fix gofmt formatting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-05 19:06:05 +00:00
Doug Lauder 5d6e6733d5 MM-45293 Index all attachment content fields in Elasticsearch (#35454)
* MM-45293 Index all Slack attachment content fields in Elasticsearch

  Previously only the "text" field from Slack attachments was indexed.
  This adds title, pretext, fallback, and field titles/values, making
  posts from integrations (JIRA, GitHub, CI bots) fully searchable.
2026-03-05 09:49:20 -05:00
Felipe Martin 7e7a1b582f fix: only match root-level JSONL files when importing a zip (#35481)
* fix: only match root-level JSONL files when importing a zip

When importing a Mattermost export zip, the code iterated over all files
to find the first .jsonl by extension. Exported attachments under data/
could themselves be .jsonl files, causing the import to pick an
attachment as the manifest instead of the actual root-level JSONL file.

Extract an IsRootJsonlFile helper in the imports package and use it in
the import process worker, mmctl validator, and bulk import test to
restrict the search to files with no directory component.

* test: add integration test for import with nested JSONL decoy file

Verify that BulkImportWithPath correctly picks the root-level JSONL
manifest and ignores a decoy .jsonl inside a subdirectory, covering
the fix from ad7f230f06.
2026-03-05 15:20:17 +01:00
unified-ci-app[bot] 7f0fa4937d Update latest minor version to 11.6.0 (#35479)
Automatic Merge
2026-03-05 08:55:22 +01:00
Ben Cooke e296a314bb [MM-67677] Adjust max autotranslations workers to 64 (#35463) 2026-03-04 16:29:40 -05:00
Devin Binnieandcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> 885ebdd4f1 [MM-67425] Add an unsupported Desktop App setting and screen for users (#35382)
* [MM-67425] Add an unsupported Desktop App setting and screen for users

* Remove console.log statements

* Fix e2e test config

* Add e2e test

* PR feedback

* Update server/channels/web/static.go

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* PR feedback

* Fix i18n

* PR feedback

* PR feedback

* PR feedback

* Gofmt

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-03-04 15:16:11 +00:00
062abe90bd Includes deleted remote cluster infos to correctly show shared user information (#35192)
* Includes deleted remote cluster infos to correctly show shared user information

* Addressing review comments

---------

Co-authored-by: Miguel de la Cruz <miguel@ctrlz.es>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-04 14:46:10 +01:00
a9a3d3f889 [MM-65587] Remove unused audit log file rotation settings (#35170)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-04 13:54:17 +01:00
Jesse HallamandMattermost Build c462720186 [MM-65822] Add directory conflict checks for plugin and import uploads (#34681)
* [MM-66789] Add directory conflict checks for plugin and import uploads

Prevent security issues where plugin uploads could write into the import
directory (or subdirectories) and vice versa by adding validation checks
at the REST API level when uploading plugins or creating import uploads.

* improved handling of root directories

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-03 16:31:05 -04:00
Mattermost Build 27d054c4d3 Prepackage Playbooks FIPS v2.7.0 (#35450) (#35456)
Automatic Merge
2026-03-03 09:25:21 +01:00
Domenico RizzoandMattermost Build 8dbfb87877 MM-29974 Adds e2e tests to the plugin list command (#34866)
* Adds e2e tests to the plugin list command

Adds end-to-end tests to the pluginListCmdF function.
These tests verify scenarios where appropriate permissions
are not available, plugins are disabled, and success cases.

* Updates plugin list command E2E tests

Removes the `pluginArg` from `pluginListCmdF` calls within end-to-end tests.
Ensures test cases accurately evaluate the `pluginListCmdF` behavior when no specific plugin name is provided as an argument, improving test coverage for default listing scenarios.

Relates to MM-29974

* Simplifies plugin test defer cleanup

Refactors defer statements in plugin E2E tests to directly call `s.th.App.UpdateConfig`.
Removes redundant anonymous function wrappers, making the test cleanup code cleaner and more concise.

Relates to MM-29974

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2026-03-03 07:40:58 +00:00
Ben Cooke 7a0f83ba72 [MM-67681] Hit the right caches for Channels.GetMany and Channels.getByNames (#35399) 2026-03-02 20:33:14 -05:00
2edc2f2c05 Translations update from Mattermost Weblate (#35446)
* Translated using Weblate (Polish)

Currently translated at 100.0% (2977 of 2977 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/pl/

* Translated using Weblate (Polish)

Currently translated at 95.4% (6731 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (Polish)

Currently translated at 95.7% (6751 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (German)

Currently translated at 100.0% (2977 of 2977 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/de/

* Translated using Weblate (Dutch)

Currently translated at 99.8% (2972 of 2977 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/nl/

* Translated using Weblate (German)

Currently translated at 98.5% (6948 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/de/

* Translated using Weblate (Dutch)

Currently translated at 99.9% (2976 of 2977 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/nl/

* Translated using Weblate (Dutch)

Currently translated at 99.8% (7040 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/nl/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 77.4% (5463 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/nb_NO/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (7053 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/nl/

* Translated using Weblate (Polish)

Currently translated at 96.0% (6771 of 7053 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

---------

Co-authored-by: master7 <marcin.karkosz@rajska.info>
Co-authored-by: jprusch <rs@schaeferbarthold.de>
Co-authored-by: Tom De Moor <tom@controlaltdieliet.be>
Co-authored-by: Frank Paul Silye <frankps@gmail.com>
2026-03-02 13:15:11 +00:00
Doug Lauder 8a4632e330 Fix flaky unit tests for TestClientCreateOutgoingOAuthConnection (#35152) 2026-03-01 18:28:42 +01:00
Maria A NunezandCursor e6cd18c90b Fix IntuneSettings config access tags to use correct permission ID (#35414)
IntuneSettings fields had access:"mobile_intune" tags, but no matching
permission exists in AllPermissions. Changed to "environment_mobile_security"
to match the existing permissions defined in permission.go.

Also added TestConfigAccessTagsMapToValidPermissions to validate all config
access tags resolve to real permissions.

Jira https://mattermost.atlassian.net/browse/MM-67693

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-27 17:53:11 -05:00
Alejandro García Montoro fa7668ae0d MM-67668: Replace Promtail with OpenTelemetry collector (#35381)
* Add container name to Docker logs

This will allow for querying Loki by container's name:

  {job="docker",container_name="mattermost-postgres"}

* Configue Loki to prepare for OTLP ingestion

- Add a volume to Loki container to get the config
- Configure Loki with the expected labels so that we can query by job,
  app, container.name...

* Add OpenTelemetry collector configuration

There are three pipelines:
1. logs/mattermost scrapes the logs from mattermost.log, parsing the
   timestamp and severity, and pushes them to Loki.
2. logs/docker scrapes the Docker logs from *-json.log, parsing the
   timestamp, the log itself and the container name, and pushes them to Loki.
3. metrics/docker scrapes the Docker socket to retrieve the containers'
   uptime values and pushes them to Prometheus.

* Replace Promtail with OpenTelemetry collector

* Update build tooling for OpenTelemetry collector

1. Make sure that the logs directory is created
2. Swap Promtail with OpenTelemetry collector

* Scrape collector to get Docker stats

Prometheus needs to scrape the OpenTelemetry collector in the exposed
port to get the Docker stats, so that we can query the uptime with
metric container_uptime_seconds, which has a container_name label to
filter by container.

* Update Grafana dashboard for Docker health checks

1. Use Prometheus as the datasource in all queries
2. Simplify the mappings to either 0 (offline, red) or 1 (online,
   green).
3. Unify all queries on container_uptime_seconds, filtering by
   container_name, and making sure that the latest value we got is at most
   15 seconds old, so that it does not show stale data.
4. Add Redis health check, that was missing
5. Update the dashboard title to Docker containers

* Tune Loki and OTel collector configs for local dev

- Switch filelog receivers to start_at: beginning so existing logs are
  ingested on collector startup, not just new entries.
- Fix Docker log timestamp layout to use 9s (variable-length nanos)
  instead of 0s (fixed-width), matching actual Docker JSON log format.
- Add ingester max_chunk_age to keep chunks open longer in the
  single-instance dev setup, so that we can ingest older logs (the
  window is max_chunk_age/2).
- Relax Loki limits for local development: allow unordered writes,
  disable old-sample rejection, and raise ingestion rate/burst to 64 MB
  to avoid throttling during bulk ingest.
2026-02-27 16:48:17 +01:00
Bill Gardner 8069cae8f8 Update plugin-calls to v1.11.1 (#35427) 2026-02-26 16:38:34 -05:00
Eva Sarafianou 24d3fed777 Update filippo.io/edwards25519 (#35422) 2026-02-25 11:27:48 -05:00
Ben Schumacher 60fbce7d03 [MM-67671] Add CJK Post search support for PostgreSQL (#35260)
Add LIKE-based CJK (Chinese, Japanese, Korean) search support for PostgreSQL, gated behind a `CJKSearch` feature flag.

PostgreSQL's built-in full-text search (`to_tsvector`/`to_tsquery`) does not support CJK languages because it relies on whitespace-based tokenization, which doesn't work for logographic/syllabic scripts that don't use spaces between words. This PR adds a `LIKE`-based fallback for search terms containing CJK characters.

**How it works:** When the `CJKSearch` feature flag is enabled and a search term contains CJK characters (Han, Hiragana, Katakana, or Hangul), the query builder generates `LIKE '%term%'` clauses instead of `to_tsvector @@ to_tsquery` expressions. Case-sensitive `LIKE` is used rather than `ILIKE` since CJK scripts have no letter casing, which also allows potential use of standard B-tree indexes.
2026-02-25 10:18:51 -05:00
ec0ad9d1b1 Translations update from Mattermost Weblate (#35404)
* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/

* Translated using Weblate (English (Australia))

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/en_AU/

* Translated using Weblate (English (Australia))

Currently translated at 95.3% (6714 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/en_AU/

* Translated using Weblate (German)

Currently translated at 99.6% (2958 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/de/

* Translated using Weblate (English (Australia))

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/en_AU/

* Translated using Weblate (English (Australia))

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/en_AU/

* Translated using Weblate (English (Australia))

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/en_AU/

* Translated using Weblate (English (Australia))

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/en_AU/

* Translated using Weblate (Polish)

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/pl/

* Translated using Weblate (English (Australia))

Currently translated at 100.0% (7039 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/en_AU/

* Translated using Weblate (Polish)

Currently translated at 94.8% (6676 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (German)

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/de/

* Translated using Weblate (German)

Currently translated at 97.3% (6849 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/de/

* Translated using Weblate (Polish)

Currently translated at 95.1% (6696 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 98.5% (6935 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/zh_Hans/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (2967 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/zh_Hans/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (7039 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/zh_Hans/

* Translated using Weblate (Polish)

Currently translated at 95.3% (6710 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

* Translated using Weblate (Dutch)

Currently translated at 99.9% (2966 of 2967 strings)

Translation: Mattermost/server
Translate-URL: https://translate.mattermost.com/projects/mattermost/server/nl/

* Translated using Weblate (Dutch)

Currently translated at 98.7% (6954 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/nl/

* Translated using Weblate (Dutch)

Currently translated at 99.7% (7021 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/nl/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (7039 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/nl/

* Translated using Weblate (Polish)

Currently translated at 95.4% (6720 of 7039 strings)

Translation: Mattermost/webapp
Translate-URL: https://translate.mattermost.com/projects/mattermost/webapp/pl/

---------

Co-authored-by: Matthew Williams <Matthew.Williams@outlook.com.au>
Co-authored-by: jprusch <rs@schaeferbarthold.de>
Co-authored-by: Roy Orbitson <roy-orbitson@devo.net.au>
Co-authored-by: master7 <marcin.karkosz@rajska.info>
Co-authored-by: ThrRip <coding@thrrip.space>
Co-authored-by: Tom De Moor <tom@controlaltdieliet.be>
2026-02-23 13:24:09 +00:00
Harshil SharmaandMattermost Build 8d511d77a8 Handled null column for scheduled post type in database (#35193)
* Handled null column for scheduled post type in database

* [skip ci]

* CI

* CI

* Minor improvement

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2026-02-23 08:45:07 +05:30
Harshil SharmaandMattermost Build b96f7c1a8d Content flagging actions implementation tests (#35035)
* Added tests for TestGetFlaggingConfiguration

* added tests for RemoveFlaggedPost

* added tests for KeepFlaggedPost

* Added tests for scrubPost and keep flagged post APp layer functions

* Added tests for DeleteAllForPost

* added tests for DeleteAllPostRemindersForPost

* Added tests for DataSpillageFooter

* Added tests for KeepRemoveFlaggedMessageConfirmationModal

* Added tests for KeepRemoveFlaggedMessageConfirmationModal

* Fixed lint errors

* lint fix

* Fixed query param

* fixed tests

* Used middleware to check for content flagging basic checks

* Added TestRequireContentFlaggingEnabled

* Updated tests

* refactoring to reduce code duplication

* review fixes

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2026-02-23 06:15:40 +05:30