* 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>
* 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.
* 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.
* 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>
* [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>
* 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>
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>
* 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.
* MM-67659 Fix handleThreadReadChanged not working when unread_mentions or unread_replies is 0
* Update type definition for ThreadReadChanged
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
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.
* Increase minimum version of NPM to 11
When we updated the Node.js version, I asked Saturn to make the Node/NPM
version checks looser because I didn't know about anything that would cause
the package-lock.json or package.json formats to change. It seems like NPM 10
is causing a few fields to be removed now, so we should require 11 to avoid
thrashing on that.
* And update the Node version
* Handled null column for scheduled post type in database
* [skip ci]
* CI
* CI
* Minor improvement
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
* MM-64490 - Add ABAC system console E2E tests
* split abac e2e tests in logical folders
* Export ABAC helpers from playwright-lib main package
* fix linter issues
* fix prettier
* fix linter
* revert unwanted changes to packa-lock
* Fix ABAC test to use refactored SystemConsoleSidebar API
* fix two failing tests
* fix prettier
* clean up before running the test to make them more reliable
* make create policy less flaky by adding better wait time
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
The "Channels" header was flashing and then disappearing when typing in
the Find Channels dialog (Ctrl/Cmd+K). This was caused by the
fetchUsersAndChannels method returning results without the groups
structure that was introduced in MM-62990.
Add validation to block updates that would create orphaned protected fields (protected=true but no source_plugin_id), which cannot be modified by anyone.
Includes test coverage for single and bulk update paths.
* fix: ensuring that webapp and mobile notifications decode special characters
* fix: linter error
* Replacing anonymous function with existing utility to escape regex
* Added missing characters to webapp handling, excluded markdown renderer from being affected
- Added tests that explicitly check for script injection
Race condition caused mousemove events to fire after reset() but before
cleanup, resulting in negative width calculations that CSS clamped to
min-width.