diff --git a/source/administration-guide/upgrade/important-upgrade-notes.rst b/source/administration-guide/upgrade/important-upgrade-notes.rst index e1a7fc27f0f..43acfc495ca 100644 --- a/source/administration-guide/upgrade/important-upgrade-notes.rst +++ b/source/administration-guide/upgrade/important-upgrade-notes.rst @@ -12,6 +12,373 @@ We recommend reviewing the `additional upgrade notes <#additional-upgrade-notes> | If you're upgrading | Then... | | from a version earlier than... | | +====================================================+==================================================================================================================================================================+ +| v11.9 | Mattermost 11.9.0 introduces a schema change in the form of a new column added to the ``incomingwebhooks`` table. The ``incomingwebhooks`` table receives an | +| | ``AccessExclusiveLock`` when adding the column; however, because PostgreSQL 11+ treats ``ADD COLUMN`` with a non-volatile constant default as a metadata-only | +| | operation, the lock is held for only microseconds and is not proportional to row count. All concurrent reads and writes are blocked only for the instant the | +| | catalog entry is updated, then immediately released — impact to concurrent operations is negligible. Zero downtime is possible when upgrading to this release. | +| | The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- up | +| | ALTER TABLE incomingwebhooks ADD COLUMN IF NOT EXISTS lastused bigint NOT NULL DEFAULT 0; | +| | -- down | +| | ALTER TABLE incomingwebhooks DROP COLUMN IF EXISTS lastused; | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | This migration adds a new ``voipdeviceid`` column (``VARCHAR(512) NOT NULL DEFAULT ''``) to the ``sessions`` table to support associating VoIP device | +| | identifiers with user sessions. The column is defined with an empty-string default, ensuring existing rows and any rows written by older server versions | +| | automatically satisfy the ``NOT NULL`` constraint without requiring a data backfill. On PostgreSQL 11 and later, adding a column with a constant default is a | +| | metadata-only operation — no table rewrite occurs — so the ``ACCESS EXCLUSIVE`` lock on ``sessions`` is held for only a brief period (typically milliseconds). | +| | Administrators on large deployments should be aware that ``sessions`` is one of the most frequently accessed tables, and any long-running transactions already | +| | holding locks on it could cause a transient increase in lock-wait times during the migration. The migrations are fully backwards-compatible and no database | +| | downtime is expected for this upgrade. The SQL queries included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- up | +| | ALTER TABLE sessions ADD COLUMN IF NOT EXISTS voipdeviceid VARCHAR(512) NOT NULL DEFAULT ''; | +| | | +| | -- down | +| | ALTER TABLE sessions DROP COLUMN IF EXISTS voipdeviceid; | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | This migration adds a composite index, ``idx_access_control_policies_type_id``, on the ``AccessControlPolicies`` table covering the ``Type`` and ``Id`` columns. | +| | The index is intended to improve query performance when filtering or looking up access control policies by type and identifier. The index is built using | +| | ``CREATE INDEX CONCURRENTLY``, meaning it is constructed in the background without blocking reads or writes on the ``AccessControlPolicies`` table. No columns, | +| | constraints, or existing indexes are modified or removed by this change. The migrations are fully backwards-compatible and no database downtime is expected for | +| | this upgrade. The SQL queries included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- Up migration (PostgreSQL) | +| | CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_access_control_policies_type_id ON AccessControlPolicies(Type, Id); | +| | | +| | .. code-block:: sql | +| | | +| | -- Down migration (PostgreSQL) | +| | DROP INDEX CONCURRENTLY IF EXISTS idx_access_control_policies_type_id; | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | This migration removes orphaned rows from the ``threadmemberships`` table — specifically, rows where the associated user is no longer a member of the channel | +| | that the thread belongs to. The cleanup is performed via a filtered ``DELETE`` using a three-way join across ``threadmemberships``, ``threads``, and | +| | ``channelmembers``. No schema objects (tables, columns, or indexes) are added or removed; only data rows are affected. Note for large instances: this migration | +| | issues a single unbatched delete that scans the entirety of ``threadmemberships`` with a join against ``threads`` and ``channelmembers``. On databases with tens | +| | of millions of rows or significant historical channel-membership churn, this query may run for an extended period, block autovacuum on ``threadmemberships``, | +| | increase WAL pressure, and contribute to replication lag. Administrators of large deployments should test execution time on a representative dataset before | +| | upgrading and consider scheduling the upgrade during a low-traffic window. The down migration contains no rollback SQL because the deleted rows cannot be | +| | recovered; this migration is irreversible. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries | +| | included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- Drop ThreadMembership rows whose user is no longer a member of the thread's channel. | +| | DELETE FROM threadmemberships WHERE (postid, userid) IN ( | +| | SELECT | +| | threadmemberships.postid, | +| | threadmemberships.userid | +| | FROM | +| | threadmemberships | +| | JOIN threads ON threads.postid = threadmemberships.postid | +| | LEFT JOIN channelmembers ON channelmembers.userid = threadmemberships.userid | +| | AND threads.channelid = channelmembers.channelid | +| | WHERE | +| | channelmembers.channelid IS NULL | +| | ); | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Migration 000199 extends the ``property_field_type`` enum in PostgreSQL by adding the new value ``'rank'`` to support rank-type property fields. The change is | +| | made via ``ALTER TYPE property_field_type ADD VALUE IF NOT EXISTS 'rank'``, which is a catalog-only operation that touches only the ``pg_enum`` system catalog | +| | and acquires no locks on user tables such as ``PropertyFields`` or ``PropertyValues``. Existing rows and application code are entirely unaffected by the | +| | addition. The rollback (down) migration is intentionally destructive: any ``PropertyFields`` rows carrying ``Type = 'rank'`` are coerced to ``'select'``, the | +| | enum is rebuilt without the ``'rank'`` value, and the ``AttributeView`` materialized view is dropped and recreated — all of which require an | +| | ``AccessExclusiveLock`` on ``PropertyFields`` and should only be executed during a maintenance window. The migrations are fully backwards-compatible and no | +| | database downtime is expected for this upgrade. The SQL queries included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- Postgres cannot remove a value from an existing enum in place, so rebuild | +| | -- the type without 'rank'. Any rows still holding 'rank' (e.g. fields created | +| | -- via the property API after this migration ran) are coerced to 'select' | +| | -- first so the recreated enum can accept them; 'select' has the same storage | +| | -- shape (single option ID). | +| | -- | +| | -- The AttributeView materialized view reads PropertyFields.Type, so Postgres | +| | -- refuses to rebuild the enum on that column while the view exists. Drop the | +| | -- view before the ALTER and recreate it afterwards. | +| | | +| | UPDATE PropertyFields SET Type = 'select' WHERE Type = 'rank'; | +| | | +| | DROP MATERIALIZED VIEW IF EXISTS AttributeView; | +| | | +| | ALTER TYPE property_field_type RENAME TO property_field_type_old; | +| | | +| | CREATE TYPE property_field_type AS ENUM ( | +| | 'text', | +| | 'select', | +| | 'multiselect', | +| | 'date', | +| | 'user', | +| | 'multiuser' | +| | ); | +| | | +| | ALTER TABLE PropertyFields | +| | ALTER COLUMN Type TYPE property_field_type USING Type::text::property_field_type; | +| | | +| | DROP TYPE property_field_type_old; | +| | | +| | -- Recreate the no-rank AttributeView (matches 000177 / 000198 down). | +| | CREATE MATERIALIZED VIEW IF NOT EXISTS AttributeView AS | +| | SELECT | +| | pv.GroupID, | +| | pv.TargetID, | +| | pv.TargetType, | +| | jsonb_object_agg( | +| | pf.Name, | +| | CASE | +| | WHEN pf.Type = 'select' THEN ( | +| | SELECT to_jsonb(options.name) | +| | FROM jsonb_to_recordset(pf.Attrs->'options') AS options(id text, name text) | +| | WHERE options.id = pv.Value #>> '{}' | +| | LIMIT 1 | +| | ) | +| | WHEN pf.Type = 'multiselect' AND jsonb_typeof(pv.Value) = 'array' THEN ( | +| | SELECT jsonb_agg(option_names.name) | +| | FROM jsonb_array_elements_text(pv.Value) AS option_id | +| | JOIN jsonb_to_recordset(pf.Attrs->'options') AS option_names(id text, name text) | +| | ON option_id = option_names.id | +| | ) | +| | ELSE pv.Value | +| | END | +| | ) AS Attributes | +| | FROM PropertyValues pv | +| | LEFT JOIN PropertyFields pf ON pf.ID = pv.FieldID | +| | WHERE (pv.DeleteAt = 0 OR pv.DeleteAt IS NULL) | +| | AND (pf.DeleteAt = 0 OR pf.DeleteAt IS NULL) | +| | AND pf.ObjectType = 'user' | +| | GROUP BY pv.GroupID, pv.TargetID, pv.TargetType; | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Migration 000195 updates up to three rows in the ``PropertyFields`` table that belong to the ``access_control`` property group, converting their ``Type`` value | +| | from ``'select'`` to ``'rank'`` and backfilling a ``rank`` integer key into each element of the ``options`` array stored in the ``Attrs`` JSONB column. The | +| | affected fields are ``classification`` (``ObjectType = 'template'``), ``system_classification`` (``ObjectType = 'system'``), and ``channel_classification`` | +| | (``ObjectType = 'channel'``), which are part of the classification-markings feature gated behind a feature flag. No schema structure changes (DDL) are made — | +| | only targeted DML ``UPDATE`` statements are executed, touching at most three rows regardless of server size. Both statements run within a single transaction, | +| | so no intermediate state is ever visible to other sessions. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. | +| | The SQL queries included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- up migration | +| | | +| | -- Convert the classification-markings property fields from 'select' to 'rank'. | +| | -- Each (Name, ObjectType) pair is matched explicitly so unrelated fields that | +| | -- happen to share a name cannot be touched. At most three rows are updated. | +| | UPDATE PropertyFields | +| | SET Type = 'rank' | +| | WHERE Type = 'select' | +| | AND GroupID = (SELECT ID FROM PropertyGroups WHERE Name = 'access_control') | +| | AND ( | +| | (Name = 'classification' AND ObjectType = 'template') | +| | OR (Name = 'system_classification' AND ObjectType = 'system') | +| | OR (Name = 'channel_classification' AND ObjectType = 'channel') | +| | ); | +| | | +| | -- Backfill a rank onto every option. | +| | UPDATE PropertyFields pf | +| | SET Attrs = jsonb_set( | +| | pf.Attrs, | +| | '{options}', | +| | ( | +| | SELECT jsonb_agg(elem.opt || jsonb_build_object('rank', elem.ord) ORDER BY elem.ord) | +| | FROM jsonb_array_elements(pf.Attrs->'options') WITH ORDINALITY AS elem(opt, ord) | +| | ) | +| | ) | +| | WHERE pf.Type = 'rank' | +| | AND pf.GroupID = (SELECT ID FROM PropertyGroups WHERE Name = 'access_control') | +| | AND ( | +| | (pf.Name = 'classification' AND pf.ObjectType = 'template') | +| | OR (pf.Name = 'system_classification' AND pf.ObjectType = 'system') | +| | OR (pf.Name = 'channel_classification' AND pf.ObjectType = 'channel') | +| | ) | +| | AND jsonb_typeof(pf.Attrs->'options') = 'array' | +| | AND jsonb_array_length(pf.Attrs->'options') > 0; | +| | | +| | .. code-block:: sql | +| | | +| | -- down migration | +| | | +| | UPDATE PropertyFields pf | +| | SET Attrs = jsonb_set( | +| | pf.Attrs, | +| | '{options}', | +| | ( | +| | SELECT jsonb_agg(elem.opt - 'rank' ORDER BY elem.ord) | +| | FROM jsonb_array_elements(pf.Attrs->'options') WITH ORDINALITY AS elem(opt, ord) | +| | ) | +| | ) | +| | WHERE pf.Type = 'rank' | +| | AND pf.GroupID = (SELECT ID FROM PropertyGroups WHERE Name = 'access_control') | +| | AND ( | +| | (pf.Name = 'classification' AND pf.ObjectType = 'template') | +| | OR (pf.Name = 'system_classification' AND pf.ObjectType = 'system') | +| | OR (pf.Name = 'channel_classification' AND pf.ObjectType = 'channel') | +| | ) | +| | AND jsonb_typeof(pf.Attrs->'options') = 'array' | +| | AND jsonb_array_length(pf.Attrs->'options') > 0; | +| | | +| | UPDATE PropertyFields | +| | SET Type = 'select' | +| | WHERE Type = 'rank' | +| | AND GroupID = (SELECT ID FROM PropertyGroups WHERE Name = 'access_control') | +| | AND ( | +| | (Name = 'classification' AND ObjectType = 'template') | +| | OR (Name = 'system_classification' AND ObjectType = 'system') | +| | OR (Name = 'channel_classification' AND ObjectType = 'channel') | +| | ); | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Migration 000196 updates data within the ``PropertyFields`` table as part of the Access Control / Properties framework. Specifically, it renames two | +| | classification field entries inside the ``access_control`` ``PropertyGroups`` group: the ``system_classification`` entry (``ObjectType = 'system'``) and the | +| | ``channel_classification`` entry (``ObjectType = 'channel'``) are both renamed to the canonical value ``classification``. The rows remain distinct because the | +| | unique index on ``PropertyFields`` incorporates ``ObjectType``, preventing collisions. This change affects at most two rows and completes near-instantly with | +| | no measurable performance impact. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included | +| | are: | +| | | +| | .. code-block:: sql | +| | | +| | -- Up migration | +| | -- Rename the system- and channel-scoped classification linked fields so all | +| | -- three classification fields share the canonical Name 'classification'. They | +| | -- remain distinct rows because the typed unique index keys on ObjectType as | +| | -- well, so template/system/channel rows do not collide. | +| | UPDATE PropertyFields | +| | SET Name = 'classification' | +| | WHERE GroupID = (SELECT ID FROM PropertyGroups WHERE Name = 'access_control') | +| | AND ( | +| | (Name = 'system_classification' AND ObjectType = 'system') | +| | OR (Name = 'channel_classification' AND ObjectType = 'channel') | +| | ); | +| | | +| | -- Down migration | +| | -- Restore the previous names so the rows can be matched by 000195's down | +| | -- migration. Identified by ObjectType since all three classification rows | +| | -- share the same Name='classification' at this point. | +| | UPDATE PropertyFields | +| | SET Name = 'system_classification' | +| | WHERE GroupID = (SELECT ID FROM PropertyGroups WHERE Name = 'access_control') | +| | AND Name = 'classification' | +| | AND ObjectType = 'system'; | +| | | +| | UPDATE PropertyFields | +| | SET Name = 'channel_classification' | +| | WHERE GroupID = (SELECT ID FROM PropertyGroups WHERE Name = 'access_control') | +| | AND Name = 'classification' | +| | AND ObjectType = 'channel'; | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Migration 000178 extends the ``AttributeView`` materialized view — part of the ABAC/property system — to add support for ``rank``-typed property fields. | +| | Previously, ``rank``-typed values were stored as raw values in the view; they are now materialized as ``{"name": , "rank": }`` JSON | +| | objects, enabling ABAC policies to compare rank values without embedding rank integers directly in policy expressions. The migration drops and recreates | +| | ``AttributeView`` in a single transaction, performing a full scan of ``PropertyValues`` and ``PropertyFields`` at migration time. Because these tables are gated | +| | behind a feature flag and expected to be empty or near-empty at the time of this migration, the performance impact is negligible for most deployments. The | +| | migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL queries included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- Extend the AttributeView matview to materialize rank-typed property values | +| | -- as {"name": , "rank": } so ABAC policies can | +| | -- compare ranks without storing rank integers in policy expressions. | +| | DROP MATERIALIZED VIEW IF EXISTS AttributeView; | +| | | +| | CREATE MATERIALIZED VIEW IF NOT EXISTS AttributeView AS | +| | SELECT | +| | pv.GroupID, | +| | pv.TargetID, | +| | pv.TargetType, | +| | jsonb_object_agg( | +| | pf.Name, | +| | CASE | +| | WHEN pf.Type = 'select' THEN ( | +| | SELECT to_jsonb(options.name) | +| | FROM jsonb_to_recordset(pf.Attrs->'options') AS options(id text, name text) | +| | WHERE options.id = pv.Value #>> '{}' | +| | LIMIT 1 | +| | ) | +| | WHEN pf.Type = 'multiselect' AND jsonb_typeof(pv.Value) = 'array' THEN ( | +| | SELECT jsonb_agg(option_names.name) | +| | FROM jsonb_array_elements_text(pv.Value) AS option_id | +| | JOIN jsonb_to_recordset(pf.Attrs->'options') AS option_names(id text, name text) | +| | ON option_id = option_names.id | +| | ) | +| | WHEN pf.Type = 'rank' THEN ( | +| | SELECT jsonb_build_object( | +| | 'name', options.name, | +| | 'rank', options.rank | +| | ) | +| | FROM jsonb_to_recordset(pf.Attrs->'options') | +| | AS options(id text, name text, rank int) | +| | WHERE options.id = pv.Value #>> '{}' | +| | LIMIT 1 | +| | ) | +| | ELSE pv.Value | +| | END | +| | ) AS Attributes | +| | FROM PropertyValues pv | +| | LEFT JOIN PropertyFields pf ON pf.ID = pv.FieldID | +| | WHERE (pv.DeleteAt = 0 OR pv.DeleteAt IS NULL) | +| | AND (pf.DeleteAt = 0 OR pf.DeleteAt IS NULL) | +| | AND pf.ObjectType = 'user' | +| | GROUP BY pv.GroupID, pv.TargetID, pv.TargetType; | +| | | +| | .. code-block:: sql | +| | | +| | -- Restore the 000177 matview definition (no rank branch). | +| | DROP MATERIALIZED VIEW IF EXISTS AttributeView; | +| | | +| | CREATE MATERIALIZED VIEW IF NOT EXISTS AttributeView AS | +| | SELECT | +| | pv.GroupID, | +| | pv.TargetID, | +| | pv.TargetType, | +| | jsonb_object_agg( | +| | pf.Name, | +| | CASE | +| | WHEN pf.Type = 'select' THEN ( | +| | SELECT to_jsonb(options.name) | +| | FROM jsonb_to_recordset(pf.Attrs->'options') AS options(id text, name text) | +| | WHERE options.id = pv.Value #>> '{}' | +| | LIMIT 1 | +| | ) | +| | WHEN pf.Type = 'multiselect' AND jsonb_typeof(pv.Value) = 'array' THEN ( | +| | SELECT jsonb_agg(option_names.name) | +| | FROM jsonb_array_elements_text(pv.Value) AS option_id | +| | JOIN jsonb_to_recordset(pf.Attrs->'options') AS option_names(id text, name text) | +| | ON option_id = option_names.id | +| | ) | +| | ELSE pv.Value | +| | END | +| | ) AS Attributes | +| | FROM PropertyValues pv | +| | LEFT JOIN PropertyFields pf ON pf.ID = pv.FieldID | +| | WHERE (pv.DeleteAt = 0 OR pv.DeleteAt IS NULL) | +| | AND (pf.DeleteAt = 0 OR pf.DeleteAt IS NULL) | +| | AND pf.ObjectType = 'user' | +| | GROUP BY pv.GroupID, pv.TargetID, pv.TargetType; | +| +------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Added an ``expiresat`` column and partial index to ``useraccesstokens`` to support PAT expiry enforcement. Large-dataset testing was not required for this | +| | migration as ``useraccesstokens`` is not a large table. ``useraccesstokens`` receives a brief ACCESS EXCLUSIVE lock when adding the column (Migration 000187, | +| | metadata-only, no table rewrite on PostgreSQL 11+), and a SHARE UPDATE EXCLUSIVE lock during the index build via CREATE INDEX CONCURRENTLY (Migration 000188), | +| | which never blocks concurrent reads or writes. The migrations are fully backwards-compatible and no database downtime is expected for this upgrade. The SQL | +| | queries included are: | +| | | +| | .. code-block:: sql | +| | | +| | -- Migration 000187 (transactional): | +| | ALTER TABLE useraccesstokens ADD COLUMN IF NOT EXISTS expiresat bigint NOT NULL DEFAULT 0; | +| | | +| | -- Migration 000188 (run via morph as nontransactional): | +| | CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_useraccesstokens_expiresat | +| | ON useraccesstokens (expiresat) | +| | WHERE expiresat > 0; | +| | | +| | -- Down migrations: | +| | DROP INDEX CONCURRENTLY IF EXISTS idx_useraccesstokens_expiresat; | +| | ALTER TABLE useraccesstokens DROP COLUMN IF EXISTS expiresat; | ++----------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | v11.8 | The Custom Profile Attributes property group is renamed from ``custom_profile_attributes`` to ``access_control``, and CPA fields and values are migrated from | | | the legacy property model to the v2 model. The functionality of the CPA feature is unchanged. Plugin developers that use CPA will need to register against the | | | new group name. | diff --git a/source/administration-guide/upgrade/open-source-components.rst b/source/administration-guide/upgrade/open-source-components.rst index 2acb77f5446..ab16f0e8ec2 100644 --- a/source/administration-guide/upgrade/open-source-components.rst +++ b/source/administration-guide/upgrade/open-source-components.rst @@ -39,6 +39,7 @@ Desktop Mobile ------- +- Mattermost Mobile v2.42.0 - `View Open Source Components `__. - Mattermost Mobile v2.41.0 - `View Open Source Components `__. - Mattermost Mobile v2.40.0 - `View Open Source Components `__. - Mattermost Mobile v2.39.0 - `View Open Source Components `__. @@ -141,6 +142,7 @@ Mobile Server ------------------------------ +- Mattermost Enterprise Edition v11.9.0 - `View Open Source Components `__. - Mattermost Enterprise Edition v11.8.0 - `View Open Source Components `__. - Mattermost Enterprise Edition v11.7.0 - `View Open Source Components `__. - Mattermost Enterprise Edition v11.6.0 - `View Open Source Components `__. diff --git a/source/deployment-guide/server/linux/deploy-rhel.rst b/source/deployment-guide/server/linux/deploy-rhel.rst index a0bdf540c79..b6e651fa573 100644 --- a/source/deployment-guide/server/linux/deploy-rhel.rst +++ b/source/deployment-guide/server/linux/deploy-rhel.rst @@ -44,7 +44,7 @@ In a terminal window, ssh onto the system that will host the Mattermost Server. .. code-block:: sh - wget https://releases.mattermost.com/11.8.2/mattermost-11.8.2-linux-amd64.tar.gz + wget https://releases.mattermost.com/11.9.0/mattermost-11.9.0-linux-amd64.tar.gz .. tab:: Current ESR diff --git a/source/deployment-guide/server/linux/deploy-tar.rst b/source/deployment-guide/server/linux/deploy-tar.rst index a1300c32c50..d2fcd140e4c 100644 --- a/source/deployment-guide/server/linux/deploy-tar.rst +++ b/source/deployment-guide/server/linux/deploy-tar.rst @@ -45,7 +45,7 @@ In a terminal window, ssh onto the system that will host the Mattermost Server. .. code-block:: sh - wget https://releases.mattermost.com/11.8.2/mattermost-11.8.2-linux-amd64.tar.gz + wget https://releases.mattermost.com/11.9.0/mattermost-11.9.0-linux-amd64.tar.gz .. tab:: Current ESR diff --git a/source/product-overview/mattermost-desktop-releases.md b/source/product-overview/mattermost-desktop-releases.md index 6785bf74da8..6ab38e2c42c 100644 --- a/source/product-overview/mattermost-desktop-releases.md +++ b/source/product-overview/mattermost-desktop-releases.md @@ -18,7 +18,7 @@ Mattermost releases a new desktop app version every 4 months, in February, May, | **Release** | **Support** | **Compatible with** | |:---|:---|:---| -| v6.2 [Download](https://github.com/mattermost/desktop/releases/tag/v6.2.2) \| {ref}`Changelog ` \| [SBOM download](https://github.com/mattermost/desktop/releases/download/v6.2.2/sbom-desktop-v6.2.2.json) | Released: 2026-05-15
Support Ends: 2027-05-15 {ref}`EXTENDED ` | {ref}`v11.8 `, {ref}`v11.7 `, {ref}`v11.6 `, {ref}`v11.5 `, {ref}`v10.11 ` | +| v6.2 [Download](https://github.com/mattermost/desktop/releases/tag/v6.2.2) \| {ref}`Changelog ` \| [SBOM download](https://github.com/mattermost/desktop/releases/download/v6.2.2/sbom-desktop-v6.2.2.json) | Released: 2026-05-15
Support Ends: 2027-05-15 {ref}`EXTENDED ` | {ref}`v11.9 `, {ref}`v11.8 `, {ref}`v11.7 `, {ref}`v11.6 `, {ref}`v11.5 `, {ref}`v10.11 ` | | v6.1 [Download](https://github.com/mattermost/desktop/releases/tag/v6.1.2) \| {ref}`Changelog ` \| [SBOM download](https://github.com/mattermost/desktop/releases/download/v6.1.2/sbom-desktop-v6.1.2.json) | Released: 2026-03-02
Support Ends: 2026-05-15 | {ref}`v11.6 `, {ref}`v11.5 `, {ref}`v11.4 `, {ref}`v11.3 `, {ref}`v11.2 `, {ref}`v10.11 ` | | v6.0 [Download](https://github.com/mattermost/desktop/releases/tag/v6.0.4) \| {ref}`Changelog ` \| [SBOM download](https://github.com/mattermost/desktop/releases/download/v6.0.4/sbom-desktop-v6.0.4.json) | Released: 2025-11-14
Support Ends: 2026-03-15 | {ref}`v11.4 `, {ref}`v11.3 `, {ref}`v11.2 `, {ref}`v11.1 `, {ref}`v11.0 `, {ref}`v10.12 `, {ref}`v10.11 ` | | v5.13 [Download](https://github.com/mattermost/desktop/releases/tag/v5.13.7) \| {ref}`Changelog ` \| [SBOM download](https://github.com/mattermost/desktop/releases/download/v5.13.7/sbom-desktop-v5.13.7.json) | Released: 2025-08-15
Support Ends: 2026-08-15 {ref}`EXTENDED ` | {ref}`v11.0 `, {ref}`v10.12 `, {ref}`v10.11 `, {ref}`v10.10 `, {ref}`v10.9 `, {ref}`v10.5 ` | diff --git a/source/product-overview/mattermost-server-releases.md b/source/product-overview/mattermost-server-releases.md index 4a3c9d9078e..765da0a706a 100644 --- a/source/product-overview/mattermost-server-releases.md +++ b/source/product-overview/mattermost-server-releases.md @@ -19,6 +19,7 @@ Mattermost releases a new server version on the 16th of each month in [binary fo | **Release** | **Released on** | **Support ends** | |:---|:---|:---| +| v11.9 [Download](https://releases.mattermost.com/11.9.0/mattermost-11.9.0-linux-amd64.tar.gz) \| {ref}`Changelog ` \|
SBOM
| 2026-07-16 | 2026-10-15 | | v11.8 [Download](https://releases.mattermost.com/11.8.2/mattermost-11.8.2-linux-amd64.tar.gz) \| {ref}`Changelog ` \|
SBOM
| 2026-06-16 | 2026-09-15 | | v11.7 [Download](https://releases.mattermost.com/11.7.6/mattermost-11.7.6-linux-amd64.tar.gz) \| {ref}`Changelog ` \|
SBOM
| 2026-05-15 | 2027-05-15 {ref}`EXTENDED ` | | v11.6 [Download](https://releases.mattermost.com/11.6.6/mattermost-11.6.6-linux-amd64.tar.gz) \| {ref}`Changelog ` \|
SBOM
| 2026-04-16 | 2026-07-15 | diff --git a/source/product-overview/release-policy.md b/source/product-overview/release-policy.md index 58a54b18ac7..e5ea9bb4722 100644 --- a/source/product-overview/release-policy.md +++ b/source/product-overview/release-policy.md @@ -57,10 +57,11 @@ gantt v11.3 :done, 2026-01-16, 2026-04-15 v11.4 :done, 2026-02-16, 2026-05-15 v11.5 :done, 2026-03-16, 2026-06-15 - v11.6 :active, 2026-04-16, 2026-07-15 + v11.6 :done, 2026-04-16, 2026-07-15 v11.7 & Desktop App v6.2 Extended Support :crit, 2026-05-15, 2027-05-15 v11.8 :active, 2026-06-16, 2026-09-15 v11.9 :active, 2026-07-16, 2026-10-15 + v11.10 :active, 2026-08-16, 2026-11-15 ``` **Timeline Legend:** diff --git a/source/product-overview/ui-ada-changelog.rst b/source/product-overview/ui-ada-changelog.rst index 5905cc0a596..c429b74f77b 100644 --- a/source/product-overview/ui-ada-changelog.rst +++ b/source/product-overview/ui-ada-changelog.rst @@ -12,6 +12,22 @@ Changelog * - Version - Change Description + * - v11.9 + - (UI) Added zoom and pan support to the image file preview: use the scroll wheel to zoom at the cursor, click-and-drag to pan, and +/-/0 keyboard shortcuts (reported on webapp). + * - v11.9 + - (UI) Added a toast notification for plugin-rejected file uploads, consistent with the existing notification for rejected downloads. + * - v11.9 + - (UI) Added a Data Spillage Handling feature discovery page in the System Console for lower-tier licenses. + * - v11.9 + - (UI) Added clearer validation messaging for invalid user attribute names in the System Console. + * - v11.9 + - (UI) Incoming webhooks now show information about the last time they were triggered. + * - v11.9 + - (UI) Threads started by a webhook are no longer highlighted for the user who owns the webhook. + * - v11.9 + - (UI) Added user setting "Auto-follow threads on channel-wide mentions" (Settings → Notifications). When disabled, @channel/@all/@here mentions no longer force thread membership; users still receive mention notifications but must manually follow the thread. + * - v11.9 + - (UI) Hardened the web app against crashes caused by components rendered by a plugin. * - v11.8 - (UI) Added a new keyboard shortcut, ``Shift`` + ``ESC``, that marks all channels, threads, and direct messages as read for a team on webapp / desktop app. * - v11.8